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.AppLoginRequest;
import de.assecutor.votianlt.dto.AppLoginResponse; import de.assecutor.votianlt.dto.AppLoginResponse;
import de.assecutor.votianlt.dto.JobWithRelatedDataDTO;
import de.assecutor.votianlt.model.AppUser; import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.model.CargoItem;
import de.assecutor.votianlt.model.Job; import de.assecutor.votianlt.model.Job;
import de.assecutor.votianlt.model.TaskEntry;
import de.assecutor.votianlt.pages.service.AppUserService; import de.assecutor.votianlt.pages.service.AppUserService;
import de.assecutor.votianlt.repository.AppUserRepository; import de.assecutor.votianlt.repository.AppUserRepository;
import de.assecutor.votianlt.repository.CargoItemRepository;
import de.assecutor.votianlt.repository.JobRepository; import de.assecutor.votianlt.repository.JobRepository;
import de.assecutor.votianlt.repository.TaskRepository;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.messaging.handler.annotation.SendTo;
@@ -40,6 +45,12 @@ public class MessageController {
@Autowired @Autowired
private JobRepository jobRepository; 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 * Handles messages sent to /app/message and broadcasts them to all subscribers of /topic/messages
*/ */
@@ -151,20 +162,20 @@ public class MessageController {
return response; 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='{}'", log.info("STOMP Response for '/app/auth/login' sent to '/user/queue/auth': success={}, message='{}', appUserId='{}'",
true, "Anmeldung erfolgreich", response.getAppUserId()); true, "Anmeldung erfolgreich", response.getAppUserId());
return response; 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 }. * Client sends to /app/jobs/assigned with payload { appUserId }.
* The response is sent back to the requesting user on /user/queue/jobs * The response is sent back to the requesting user on /user/queue/jobs
*/ */
@MessageMapping("/jobs/assigned") @MessageMapping("/jobs/assigned")
@SendToUser("/queue/jobs") @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); log.info("STOMP Endpoint '/app/jobs/assigned' called with data: {}", request);
if (request == null || !request.containsKey("appUserId")) { if (request == null || !request.containsKey("appUserId")) {
@@ -180,9 +191,19 @@ public class MessageController {
// Find jobs assigned to this app user // Find jobs assigned to this app user
List<Job> assignedJobs = jobRepository.findByAppUser(appUserId); 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; package de.assecutor.votianlt.model;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data; import lombok.Data;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
@@ -13,6 +15,7 @@ import java.time.LocalDateTime;
public class AppUser { public class AppUser {
@Id @Id
@JsonIgnore
private ObjectId id; private ObjectId id;
@Field("bezeichnung") @Field("bezeichnung")
@@ -62,4 +65,13 @@ public class AppUser {
this.erstelltAm = LocalDateTime.now(); this.erstelltAm = LocalDateTime.now();
this.aktualisiertAm = 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; package de.assecutor.votianlt.model;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@@ -14,6 +16,7 @@ import org.springframework.data.mongodb.core.mapping.Field;
@Document(collection = "cargo_items") @Document(collection = "cargo_items")
public class CargoItem { public class CargoItem {
@Id @Id
@JsonIgnore
private ObjectId id; private ObjectId id;
@Field("job_id") @Field("job_id")
@@ -36,5 +39,14 @@ public class CargoItem {
@Field("height_mm") @Field("height_mm")
private Double heightMm; 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; package de.assecutor.votianlt.model;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data; import lombok.Data;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
@@ -14,6 +16,7 @@ import java.math.BigDecimal;
@Document(collection = "jobs") @Document(collection = "jobs")
public class Job { public class Job {
@Id @Id
@JsonIgnore
private ObjectId id; private ObjectId id;
// Metadaten // Metadaten
@@ -122,4 +125,13 @@ public class Job {
// Preis (netto) // Preis (netto)
@Field("price") @Field("price")
private BigDecimal 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; package de.assecutor.votianlt.model;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@@ -14,12 +16,32 @@ import org.springframework.data.mongodb.core.mapping.Field;
@Document(collection = "tasks") @Document(collection = "tasks")
public class TaskEntry { public class TaskEntry {
@Id @Id
@JsonIgnore
private ObjectId id; private ObjectId id;
@Field("job_id") @Field("job_id")
@JsonIgnore
private ObjectId jobId; private ObjectId jobId;
@Field("text") @Field("text")
private String 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");
}
}
}