Erweiterungen

This commit is contained in:
2025-09-02 19:01:07 +02:00
parent 4f3f75c8a8
commit f444f50538
7 changed files with 168 additions and 6 deletions

View File

@@ -2,11 +2,16 @@ package de.assecutor.votianlt.controller;
import de.assecutor.votianlt.dto.AppLoginRequest;
import de.assecutor.votianlt.dto.AppLoginResponse;
import de.assecutor.votianlt.dto.JobWithRelatedDataDTO;
import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.model.CargoItem;
import de.assecutor.votianlt.model.Job;
import de.assecutor.votianlt.model.TaskEntry;
import de.assecutor.votianlt.pages.service.AppUserService;
import de.assecutor.votianlt.repository.AppUserRepository;
import de.assecutor.votianlt.repository.CargoItemRepository;
import de.assecutor.votianlt.repository.JobRepository;
import de.assecutor.votianlt.repository.TaskRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
@@ -40,6 +45,12 @@ public class MessageController {
@Autowired
private JobRepository jobRepository;
@Autowired
private CargoItemRepository cargoItemRepository;
@Autowired
private TaskRepository taskRepository;
/**
* Handles messages sent to /app/message and broadcasts them to all subscribers of /topic/messages
*/
@@ -151,20 +162,20 @@ public class MessageController {
return response;
}
AppLoginResponse response = new AppLoginResponse(true, "Anmeldung erfolgreich", user.getId() != null ? user.getId().toHexString() : null);
AppLoginResponse response = new AppLoginResponse(true, "Anmeldung erfolgreich", user.getIdAsString());
log.info("STOMP Response for '/app/auth/login' sent to '/user/queue/auth': success={}, message='{}', appUserId='{}'",
true, "Anmeldung erfolgreich", response.getAppUserId());
return response;
}
/**
* Endpoint to retrieve jobs assigned to a specific app user.
* Endpoint to retrieve jobs assigned to a specific app user with related cargo items and tasks.
* Client sends to /app/jobs/assigned with payload { appUserId }.
* The response is sent back to the requesting user on /user/queue/jobs
*/
@MessageMapping("/jobs/assigned")
@SendToUser("/queue/jobs")
public List<Job> handleGetAssignedJobs(Map<String, Object> request) {
public List<JobWithRelatedDataDTO> handleGetAssignedJobs(Map<String, Object> request) {
log.info("STOMP Endpoint '/app/jobs/assigned' called with data: {}", request);
if (request == null || !request.containsKey("appUserId")) {
@@ -180,9 +191,19 @@ public class MessageController {
// Find jobs assigned to this app user
List<Job> assignedJobs = jobRepository.findByAppUser(appUserId);
log.info("STOMP Response for '/app/jobs/assigned' sent to '/user/queue/jobs': {} jobs found for appUserId='{}'",
assignedJobs.size(), appUserId);
return assignedJobs;
// For each job, fetch related cargo items and tasks
List<JobWithRelatedDataDTO> jobsWithRelatedData = assignedJobs.stream()
.map(job -> {
List<CargoItem> cargoItems = cargoItemRepository.findByJobId(job.getId());
List<TaskEntry> tasks = taskRepository.findByJobId(job.getId());
return new JobWithRelatedDataDTO(job, cargoItems, tasks);
})
.toList();
log.info("STOMP Response for '/app/jobs/assigned' sent to '/user/queue/jobs': {} jobs with related data found for appUserId='{}'",
jobsWithRelatedData.size(), appUserId);
return jobsWithRelatedData;
}
}

View File

@@ -0,0 +1,23 @@
package de.assecutor.votianlt.dto;
import de.assecutor.votianlt.model.CargoItem;
import de.assecutor.votianlt.model.Job;
import de.assecutor.votianlt.model.TaskEntry;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* DTO for returning job data with related cargo items and tasks.
* This combines Job entity with its associated CargoItems and TaskEntries.
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JobWithRelatedDataDTO {
private Job job;
private List<CargoItem> cargoItems;
private List<TaskEntry> tasks;
}

View File

@@ -1,5 +1,7 @@
package de.assecutor.votianlt.model;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
@@ -13,6 +15,7 @@ import java.time.LocalDateTime;
public class AppUser {
@Id
@JsonIgnore
private ObjectId id;
@Field("bezeichnung")
@@ -62,4 +65,13 @@ public class AppUser {
this.erstelltAm = LocalDateTime.now();
this.aktualisiertAm = LocalDateTime.now();
}
/**
* Returns the ObjectId as string for JSON serialization.
* This ensures that the app user id is returned as a string when users are retrieved via API.
*/
@JsonGetter("id")
public String getIdAsString() {
return id != null ? id.toString() : null;
}
}

View File

@@ -1,5 +1,7 @@
package de.assecutor.votianlt.model;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -14,6 +16,7 @@ import org.springframework.data.mongodb.core.mapping.Field;
@Document(collection = "cargo_items")
public class CargoItem {
@Id
@JsonIgnore
private ObjectId id;
@Field("job_id")
@@ -36,5 +39,14 @@ public class CargoItem {
@Field("height_mm")
private Double heightMm;
/**
* Returns the ObjectId as string for JSON serialization.
* This ensures that the cargo item id is returned as a string when items are retrieved via API.
*/
@JsonGetter("id")
public String getIdAsString() {
return id != null ? id.toString() : null;
}
}

View File

@@ -1,5 +1,7 @@
package de.assecutor.votianlt.model;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
@@ -14,6 +16,7 @@ import java.math.BigDecimal;
@Document(collection = "jobs")
public class Job {
@Id
@JsonIgnore
private ObjectId id;
// Metadaten
@@ -122,4 +125,13 @@ public class Job {
// Preis (netto)
@Field("price")
private BigDecimal price;
/**
* Returns the ObjectId as string for JSON serialization.
* This ensures that the job id is returned as a string when jobs are retrieved via API.
*/
@JsonGetter("id")
public String getIdAsString() {
return id != null ? id.toString() : null;
}
}

View File

@@ -1,5 +1,7 @@
package de.assecutor.votianlt.model;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -14,12 +16,32 @@ import org.springframework.data.mongodb.core.mapping.Field;
@Document(collection = "tasks")
public class TaskEntry {
@Id
@JsonIgnore
private ObjectId id;
@Field("job_id")
@JsonIgnore
private ObjectId jobId;
@Field("text")
private String text;
/**
* Returns the ObjectId as string for JSON serialization.
* This ensures that the task id is returned as a string when jobs are retrieved via API.
*/
@JsonGetter("id")
public String getIdAsString() {
return id != null ? id.toString() : null;
}
/**
* Returns the job ObjectId as string for JSON serialization.
* This ensures that the job id is returned as a string instead of ObjectId object.
*/
@JsonGetter("jobId")
public String getJobIdAsString() {
return jobId != null ? jobId.toString() : null;
}
}

View File

@@ -0,0 +1,60 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import de.assecutor.votianlt.dto.JobWithRelatedDataDTO;
import de.assecutor.votianlt.model.CargoItem;
import de.assecutor.votianlt.model.Job;
import de.assecutor.votianlt.model.TaskEntry;
import org.bson.types.ObjectId;
import java.util.List;
/**
* Simple test to verify JSON serialization of ObjectIds as strings
*/
public class JsonSerializationTest {
public static void main(String[] args) throws Exception {
System.out.println("[DEBUG_LOG] Testing Job ID serialization...");
// Create test data
Job job = new Job();
job.setId(new ObjectId());
job.setJobNumber("TEST-001");
CargoItem cargo = new CargoItem();
cargo.setId(new ObjectId());
cargo.setJobId(job.getId());
cargo.setDescription("Test cargo");
TaskEntry task = new TaskEntry();
task.setId(new ObjectId());
task.setJobId(job.getId());
task.setText("Test task");
JobWithRelatedDataDTO dto = new JobWithRelatedDataDTO(job, List.of(cargo), List.of(task));
// Serialize to JSON
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(dto);
System.out.println("[DEBUG_LOG] Serialized JSON: " + json);
// Check if job ID is serialized as string
if (json.contains("\"id\":\"" + job.getId().toString() + "\"")) {
System.out.println("[DEBUG_LOG] ✓ Job ID correctly serialized as string");
} else if (json.contains("\"id\":{")) {
System.out.println("[DEBUG_LOG] ✗ Job ID serialized as ObjectId object");
} else {
System.out.println("[DEBUG_LOG] ? Job ID serialization format unclear");
}
// Test individual Job serialization
String jobJson = mapper.writeValueAsString(job);
System.out.println("[DEBUG_LOG] Individual Job JSON: " + jobJson);
if (jobJson.contains("\"id\":\"" + job.getId().toString() + "\"")) {
System.out.println("[DEBUG_LOG] ✓ Individual Job ID correctly serialized as string");
} else {
System.out.println("[DEBUG_LOG] ✗ Individual Job ID not serialized as string");
}
}
}