Erweiterungen

This commit is contained in:
2025-09-15 20:33:35 +02:00
parent 08db550f0d
commit 9aef567ef9
2 changed files with 80 additions and 122 deletions

View File

@@ -20,6 +20,7 @@ import de.assecutor.votianlt.model.Barcode;
import de.assecutor.votianlt.model.Signature; import de.assecutor.votianlt.model.Signature;
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 lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
@@ -29,6 +30,7 @@ import org.springframework.stereotype.Component;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
@@ -450,8 +452,8 @@ public class MessageController {
emailService.sendTaskCompletionNotification(jobId, taskType, taskIdStr, completedBy); emailService.sendTaskCompletionNotification(jobId, taskType, taskIdStr, completedBy);
// Check if this was the last task and send job completion notification // Check if all tasks are completed and handle job completion
emailService.checkAndSendJobCompletionNotification(jobId, completedBy); checkAndHandleJobCompletion(jobId, completedBy);
} catch (Exception e) { } catch (Exception e) {
log.warn("Failed to send task completion email notification for task {}: {}", taskIdStr, log.warn("Failed to send task completion email notification for task {}: {}", taskIdStr,
e.getMessage()); e.getMessage());
@@ -467,6 +469,66 @@ public class MessageController {
} }
} }
private void checkAndHandleJobCompletion(ObjectId jobId, String completedBy) {
try {
// Check if all tasks for this job are completed
var allTasks = taskRepository.findByJobIdOrderByTaskOrderAsc(jobId);
if (allTasks.isEmpty()) {
log.debug("No tasks found for job {}", jobId);
return;
}
boolean allCompleted = allTasks.stream().allMatch(task -> task.isCompleted());
if (allCompleted) {
log.info("All tasks completed for job {}, updating job status and sending completion notification",
jobId);
// Update job status to COMPLETED
updateJobStatusToCompleted(jobId);
// Send completion notification
try {
emailService.sendJobCompletionNotification(jobId, completedBy);
} catch (Exception e) {
log.warn("Failed to send job completion notification for job {}: {}", jobId, e.getMessage());
}
} else {
long completedCount = allTasks.stream().mapToLong(task -> task.isCompleted() ? 1L : 0L).sum();
log.debug("Job {} not yet complete: {}/{} tasks completed", jobId, completedCount, allTasks.size());
}
} catch (Exception e) {
log.error("Failed to check job completion for job {}: {}", jobId, e.getMessage(), e);
}
}
private void updateJobStatusToCompleted(ObjectId jobId) {
try {
Optional<Job> jobOpt = jobRepository.findById(jobId);
if (jobOpt.isEmpty()) {
log.warn("Job not found for status update: {}", jobId);
return;
}
Job job = jobOpt.get();
JobStatus oldStatus = job.getStatus();
// Only update if not already completed
if (job.getStatus() != JobStatus.COMPLETED) {
job.setStatus(JobStatus.COMPLETED);
job.setUpdatedAt(LocalDateTime.now());
jobRepository.save(job);
log.info("Job status updated from {} to COMPLETED for job {}", oldStatus != null ? oldStatus : "null",
job.getJobNumber());
} else {
log.debug("Job {} already has COMPLETED status", job.getJobNumber());
}
} catch (Exception e) {
log.error("Failed to update job status to COMPLETED for job {}: {}", jobId, e.getMessage(), e);
}
}
/** /**
* Store the mapping between userId and clientId for active session * Store the mapping between userId and clientId for active session
*/ */

View File

@@ -2,7 +2,6 @@ package de.assecutor.votianlt.service;
import de.assecutor.votianlt.model.AppUser; import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.model.Job; import de.assecutor.votianlt.model.Job;
import de.assecutor.votianlt.model.JobStatus;
import de.assecutor.votianlt.model.User; import de.assecutor.votianlt.model.User;
import de.assecutor.votianlt.repository.AppUserRepository; import de.assecutor.votianlt.repository.AppUserRepository;
import de.assecutor.votianlt.repository.JobRepository; import de.assecutor.votianlt.repository.JobRepository;
@@ -43,22 +42,9 @@ public class EmailService {
Job job = jobOpt.get(); Job job = jobOpt.get();
// Find the app user who completed the task // Find the app user who completed the task
Optional<AppUser> appUserOpt = appUserRepository.findByAppCode(completedBy); Optional<User> userOpt = userRepository.findById(new ObjectId(job.getCreatedBy()));
if (appUserOpt.isEmpty()) {
log.warn("AppUser not found for task completion notification: {}", completedBy);
return;
}
AppUser appUser = appUserOpt.get();
// Find the owner (User) of the AppUser
if (appUser.getOwner() == null) {
log.warn("AppUser has no owner for task completion notification: {}", completedBy);
return;
}
Optional<User> userOpt = userRepository.findById(appUser.getOwner());
if (userOpt.isEmpty()) { if (userOpt.isEmpty()) {
log.warn("Owner user not found for task completion notification: {}", appUser.getOwner()); log.warn("User not found for task completion notification: {}", job.getId());
return; return;
} }
User user = userOpt.get(); User user = userOpt.get();
@@ -70,7 +56,7 @@ public class EmailService {
} }
// Send email // Send email
sendEmail(user, job, taskType, taskId, appUser); sendEmail(user, job, taskType);
log.info("Task completion notification sent to {} for job {} task {}", user.getEmail(), job.getJobNumber(), log.info("Task completion notification sent to {} for job {} task {}", user.getEmail(), job.getJobNumber(),
taskId); taskId);
@@ -80,7 +66,7 @@ public class EmailService {
} }
} }
private void sendEmail(User user, Job job, String taskType, String taskId, AppUser appUser) { private void sendEmail(User user, Job job, String taskType) {
SimpleMailMessage message = new SimpleMailMessage(); SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(smtpUsername); message.setFrom(smtpUsername);
message.setTo(user.getEmail()); message.setTo(user.getEmail());
@@ -88,7 +74,7 @@ public class EmailService {
"Aufgabe abgeschlossen - " + (job.getJobNumber() != null ? job.getJobNumber() : "Job " + job.getId())); "Aufgabe abgeschlossen - " + (job.getJobNumber() != null ? job.getJobNumber() : "Job " + job.getId()));
String fullName = buildFullName(user); String fullName = buildFullName(user);
String appUserName = buildAppUserName(appUser); String appUserName = buildAppUserName(user);
String taskTypeName = getTaskTypeDisplayName(taskType); String taskTypeName = getTaskTypeDisplayName(taskType);
StringBuilder body = new StringBuilder(); StringBuilder body = new StringBuilder();
@@ -137,18 +123,15 @@ public class EmailService {
return fullName.isEmpty() ? "Benutzer" : fullName; return fullName.isEmpty() ? "Benutzer" : fullName;
} }
private String buildAppUserName(AppUser appUser) { private String buildAppUserName(User user) {
StringBuilder name = new StringBuilder(); StringBuilder name = new StringBuilder();
if (appUser.getVorname() != null && !appUser.getVorname().isBlank()) { if (user.getFirstname() != null && !user.getFirstname().isBlank()) {
name.append(appUser.getVorname()).append(" "); name.append(user.getFirstname()).append(" ");
} }
if (appUser.getNachname() != null && !appUser.getNachname().isBlank()) { if (user.getName() != null && !user.getName().isBlank()) {
name.append(appUser.getNachname()); name.append(user.getName());
} }
String fullName = name.toString().trim(); String fullName = name.toString().trim();
if (fullName.isEmpty() && appUser.getBezeichnung() != null && !appUser.getBezeichnung().isBlank()) {
return appUser.getBezeichnung();
}
return fullName.isEmpty() ? "App-Benutzer" : fullName; return fullName.isEmpty() ? "App-Benutzer" : fullName;
} }
@@ -166,54 +149,7 @@ public class EmailService {
}; };
} }
private String buildRouteString(Job job) { public void sendJobCompletionNotification(ObjectId jobId, String completedBy) {
if (job.getPickupCity() == null && job.getDeliveryCity() == null) {
return null;
}
StringBuilder route = new StringBuilder();
if (job.getPickupCity() != null) {
route.append(job.getPickupCity());
}
if (job.getPickupCity() != null && job.getDeliveryCity() != null) {
route.append("");
}
if (job.getDeliveryCity() != null) {
route.append(job.getDeliveryCity());
}
return route.toString();
}
public void checkAndSendJobCompletionNotification(ObjectId jobId, String completedBy) {
try {
// Check if all tasks for this job are completed
var allTasks = taskRepository.findByJobIdOrderByTaskOrderAsc(jobId);
if (allTasks.isEmpty()) {
log.debug("No tasks found for job {}", jobId);
return;
}
boolean allCompleted = allTasks.stream().allMatch(task -> task.isCompleted());
if (allCompleted) {
log.info("All tasks completed for job {}, updating job status and sending completion notification",
jobId);
// Update job status to COMPLETED
updateJobStatusToCompleted(jobId);
// Send completion notification
sendJobCompletionNotification(jobId, completedBy);
} else {
long completedCount = allTasks.stream().mapToLong(task -> task.isCompleted() ? 1L : 0L).sum();
log.debug("Job {} not yet complete: {}/{} tasks completed", jobId, completedCount, allTasks.size());
}
} catch (Exception e) {
log.error("Failed to check job completion for job {}: {}", jobId, e.getMessage(), e);
}
}
private void sendJobCompletionNotification(ObjectId jobId, String completedBy) {
try { try {
// Load job // Load job
Optional<Job> jobOpt = jobRepository.findById(jobId); Optional<Job> jobOpt = jobRepository.findById(jobId);
@@ -224,22 +160,9 @@ public class EmailService {
Job job = jobOpt.get(); Job job = jobOpt.get();
// Find the app user who completed the last task // Find the app user who completed the last task
Optional<AppUser> appUserOpt = appUserRepository.findByAppCode(completedBy); Optional<User> userOpt = userRepository.findById(new ObjectId(job.getCreatedBy()));
if (appUserOpt.isEmpty()) {
log.warn("AppUser not found for job completion notification: {}", completedBy);
return;
}
AppUser appUser = appUserOpt.get();
// Find the owner (User) of the AppUser
if (appUser.getOwner() == null) {
log.warn("AppUser has no owner for job completion notification: {}", completedBy);
return;
}
Optional<User> userOpt = userRepository.findById(appUser.getOwner());
if (userOpt.isEmpty()) { if (userOpt.isEmpty()) {
log.warn("Owner user not found for job completion notification: {}", appUser.getOwner()); log.warn("User not found for job completion notification: {}", completedBy);
return; return;
} }
User user = userOpt.get(); User user = userOpt.get();
@@ -251,7 +174,7 @@ public class EmailService {
} }
// Send job completion email // Send job completion email
sendJobCompletionEmail(user, job, appUser); sendJobCompletionEmail(user, job);
log.info("Job completion notification sent to {} for job {}", user.getEmail(), job.getJobNumber()); log.info("Job completion notification sent to {} for job {}", user.getEmail(), job.getJobNumber());
} catch (Exception e) { } catch (Exception e) {
@@ -259,7 +182,7 @@ public class EmailService {
} }
} }
private void sendJobCompletionEmail(User user, Job job, AppUser appUser) { private void sendJobCompletionEmail(User user, Job job) {
SimpleMailMessage message = new SimpleMailMessage(); SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(smtpUsername); message.setFrom(smtpUsername);
message.setTo(user.getEmail()); message.setTo(user.getEmail());
@@ -267,7 +190,7 @@ public class EmailService {
"Job abgeschlossen - " + (job.getJobNumber() != null ? job.getJobNumber() : "Job " + job.getId())); "Job abgeschlossen - " + (job.getJobNumber() != null ? job.getJobNumber() : "Job " + job.getId()));
String fullName = buildFullName(user); String fullName = buildFullName(user);
String appUserName = buildAppUserName(appUser); String appUserName = buildAppUserName(user);
// Count completed tasks // Count completed tasks
var allTasks = taskRepository.findByJobIdOrderByTaskOrderAsc(job.getId()); var allTasks = taskRepository.findByJobIdOrderByTaskOrderAsc(job.getId());
@@ -306,33 +229,6 @@ public class EmailService {
mailSender.send(message); mailSender.send(message);
} }
private void updateJobStatusToCompleted(ObjectId jobId) {
try {
Optional<Job> jobOpt = jobRepository.findById(jobId);
if (jobOpt.isEmpty()) {
log.warn("Job not found for status update: {}", jobId);
return;
}
Job job = jobOpt.get();
JobStatus oldStatus = job.getStatus();
// Only update if not already completed
if (job.getStatus() != JobStatus.COMPLETED) {
job.setStatus(JobStatus.COMPLETED);
job.setUpdatedAt(java.time.LocalDateTime.now());
jobRepository.save(job);
log.info("Job status updated from {} to COMPLETED for job {}", oldStatus != null ? oldStatus : "null",
job.getJobNumber());
} else {
log.debug("Job {} already has COMPLETED status", job.getJobNumber());
}
} catch (Exception e) {
log.error("Failed to update job status to COMPLETED for job {}: {}", jobId, e.getMessage(), e);
}
}
public void sendJobCreationNotification(ObjectId jobId, String createdBy) { public void sendJobCreationNotification(ObjectId jobId, String createdBy) {
try { try {
// Load job // Load job