diff --git a/src/main/java/de/assecutor/votianlt/model/Job.java b/src/main/java/de/assecutor/votianlt/model/Job.java index a1d1e91..600ee93 100644 --- a/src/main/java/de/assecutor/votianlt/model/Job.java +++ b/src/main/java/de/assecutor/votianlt/model/Job.java @@ -5,6 +5,7 @@ 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 org.springframework.data.annotation.Transient; import java.time.LocalDate; import java.time.LocalDateTime; @@ -71,9 +72,6 @@ public class Job { @Field("pickup_city") private String pickupCity; - @Field("save_pickup_address") - private boolean savePickupAddress; - // Lieferadresse @Field("delivery_company") private String deliveryCompany; @@ -105,9 +103,6 @@ public class Job { @Field("delivery_city") private String deliveryCity; - @Field("save_delivery_address") - private boolean saveDeliveryAddress; - // Digitale Abwicklung per App @Field("digital_processing") private boolean digitalProcessing; @@ -126,10 +121,6 @@ public class Job { @Field("remark") private String remark; - // Aufgaben - @Field("tasks") - private List tasks; - // Preis (netto) @Field("price") private BigDecimal price; diff --git a/src/main/java/de/assecutor/votianlt/model/TaskEntry.java b/src/main/java/de/assecutor/votianlt/model/TaskEntry.java new file mode 100644 index 0000000..4deb6a6 --- /dev/null +++ b/src/main/java/de/assecutor/votianlt/model/TaskEntry.java @@ -0,0 +1,25 @@ +package de.assecutor.votianlt.model; + +import lombok.AllArgsConstructor; +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; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Document(collection = "tasks") +public class TaskEntry { + @Id + private ObjectId id; + + @Field("job_id") + private ObjectId jobId; + + @Field("text") + private String text; +} + diff --git a/src/main/java/de/assecutor/votianlt/pages/add_job/service/AddJobService.class b/src/main/java/de/assecutor/votianlt/pages/add_job/service/AddJobService.class deleted file mode 100644 index 9d3d0ef..0000000 Binary files a/src/main/java/de/assecutor/votianlt/pages/add_job/service/AddJobService.class and /dev/null differ diff --git a/src/main/java/de/assecutor/votianlt/pages/add_job/service/AddJobService.java b/src/main/java/de/assecutor/votianlt/pages/add_job/service/AddJobService.java index 684b1d7..b50429c 100644 --- a/src/main/java/de/assecutor/votianlt/pages/add_job/service/AddJobService.java +++ b/src/main/java/de/assecutor/votianlt/pages/add_job/service/AddJobService.java @@ -3,9 +3,12 @@ package de.assecutor.votianlt.pages.add_job.service; import de.assecutor.votianlt.model.CargoItem; import de.assecutor.votianlt.model.Job; import de.assecutor.votianlt.model.JobStatus; -import de.assecutor.votianlt.repository.CargoItemRepository; +import de.assecutor.votianlt.model.TaskEntry; import de.assecutor.votianlt.repository.JobRepository; +import de.assecutor.votianlt.repository.TaskRepository; import de.assecutor.votianlt.security.SecurityService; +import de.assecutor.votianlt.repository.CargoItemRepository; +import java.util.Objects; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.bson.types.ObjectId; @@ -15,22 +18,22 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; @Service @RequiredArgsConstructor @Slf4j public class AddJobService { - private final JobRepository jobRepository; private final CargoItemRepository cargoItemRepository; + private final JobRepository jobRepository; + private final TaskRepository taskRepository; private final SecurityService securityService; /** - * Speichert einen neuen Auftrag samt CargoItems (separat in cargo_items) + * Speichert einen neuen Auftrag samt CargoItems und Tasks * @param job der Auftrag * @param transientCargo zugehörige, noch nicht gespeicherte CargoItems aus der View */ - public Job addJobWithCargo(Job job, List transientCargo) { + public Job addJobWithCargo(Job job, List transientCargo, List transientTasks) { try { // Metadaten setzen LocalDateTime now = LocalDateTime.now(); @@ -46,23 +49,42 @@ public class AddJobService { // Auftrag speichern Job savedJob = jobRepository.save(job); + final ObjectId jobId = savedJob.getId(); + boolean modified = false; // CargoItems separat mit Referenz auf Job speichern, IDs im Job verknüpfen if (transientCargo != null && !transientCargo.isEmpty()) { - final ObjectId jobId = savedJob.getId(); - List itemsWithJob = transientCargo.stream().map(ci -> { - CargoItem copy = new CargoItem(); - copy.setJobId(jobId); - copy.setDescription(ci.getDescription()); - copy.setQuantity(ci.getQuantity()); - copy.setWeightKg(ci.getWeightKg()); - copy.setLengthMm(ci.getLengthMm()); - copy.setWidthMm(ci.getWidthMm()); - copy.setHeightMm(ci.getHeightMm()); - return copy; - }).collect(java.util.stream.Collectors.toList()); - List savedItems = cargoItemRepository.saveAll(itemsWithJob); - List cargoIds = savedItems.stream().map(CargoItem::getId).collect(java.util.stream.Collectors.toList()); + List itemsWithJob = transientCargo.stream() + .filter(Objects::nonNull) + .filter(ci -> ci.getDescription() != null && !ci.getDescription().isBlank()) + .map(ci -> { + CargoItem copy = new CargoItem(); + copy.setJobId(jobId); + copy.setDescription(ci.getDescription()); + copy.setQuantity(ci.getQuantity()); + copy.setWeightKg(ci.getWeightKg()); + copy.setLengthMm(ci.getLengthMm()); + copy.setWidthMm(ci.getWidthMm()); + copy.setHeightMm(ci.getHeightMm()); + return copy; + }).toList(); + var savedItems = cargoItemRepository.saveAll(itemsWithJob); + var cargoIds = savedItems.stream().map(CargoItem::getId).toList(); + modified = true; + // Tasks separat speichern und referenzieren + if (transientTasks != null && !transientTasks.isEmpty()) { + var prepared = transientTasks.stream() + .filter(Objects::nonNull) + .filter(te -> te.getText() != null && !te.getText().isBlank()) + .peek(te -> te.setJobId(jobId)) + .toList(); + var savedTasks = taskRepository.saveAll(prepared); + var taskIds = savedTasks.stream().map(de.assecutor.votianlt.model.TaskEntry::getId).toList(); + modified = true; + } + } + + if (modified) { savedJob = jobRepository.save(savedJob); } @@ -75,36 +97,6 @@ public class AddJobService { } } - /** - * Speichert einen neuen Auftrag in der MongoDB - */ - public Job addJob(Job job) { - try { - // Metadaten setzen - LocalDateTime now = LocalDateTime.now(); - job.setCreatedAt(now); - job.setUpdatedAt(now); - job.setStatus(JobStatus.CREATED); - job.setCreatedBy(securityService.getCurrentUsername()); - - // Auftragsnummer generieren, falls nicht vorhanden - if (job.getJobNumber() == null || job.getJobNumber().isEmpty()) { - job.setJobNumber(generateJobNumber()); - } - - // Auftrag speichern - Job savedJob = jobRepository.save(job); - - log.info("Auftrag erfolgreich gespeichert: {}", savedJob.getJobNumber()); - - return savedJob; - - } catch (Exception e) { - log.error("Fehler beim Speichern des Auftrags: {}", e.getMessage(), e); - throw new RuntimeException("Auftrag konnte nicht gespeichert werden: " + e.getMessage()); - } - } - /** * Aktualisiert einen bestehenden Auftrag */ @@ -206,7 +198,7 @@ public class AddJobService { /** * Speichert einen Auftrag als Entwurf (für automatisches Speichern) */ - public Job saveDraft(Job job) { + public void saveDraft(Job job) { try { // Prüfen ob bereits ein Entwurf für diesen Benutzer existiert String currentUser = securityService.getCurrentUsername(); @@ -215,7 +207,7 @@ public class AddJobService { Job draftJob; if (!existingDrafts.isEmpty()) { // Bestehenden Entwurf aktualisieren - draftJob = existingDrafts.get(0); + draftJob = existingDrafts.getFirst(); updateJobFromForm(draftJob, job); draftJob.setUpdatedAt(LocalDateTime.now()); } else { @@ -236,8 +228,6 @@ public class AddJobService { Job savedDraft = jobRepository.save(draftJob); log.info("Entwurf automatisch gespeichert für Benutzer: {}", currentUser); - return savedDraft; - } catch (Exception e) { log.error("Fehler beim Speichern des Entwurfs: {}", e.getMessage(), e); throw new RuntimeException("Entwurf konnte nicht gespeichert werden: " + e.getMessage()); @@ -261,7 +251,6 @@ public class AddJobService { existingJob.setPickupAddressAddition(formJob.getPickupAddressAddition()); existingJob.setPickupZip(formJob.getPickupZip()); existingJob.setPickupCity(formJob.getPickupCity()); - existingJob.setSavePickupAddress(formJob.isSavePickupAddress()); // Delivery address existingJob.setDeliveryCompany(formJob.getDeliveryCompany()); @@ -274,7 +263,6 @@ public class AddJobService { existingJob.setDeliveryAddressAddition(formJob.getDeliveryAddressAddition()); existingJob.setDeliveryZip(formJob.getDeliveryZip()); existingJob.setDeliveryCity(formJob.getDeliveryCity()); - existingJob.setSaveDeliveryAddress(formJob.isSaveDeliveryAddress()); // Digital processing existingJob.setDigitalProcessing(formJob.isDigitalProcessing()); @@ -284,7 +272,6 @@ public class AddJobService { existingJob.setPickupDate(formJob.getPickupDate()); existingJob.setDeliveryDate(formJob.getDeliveryDate()); existingJob.setRemark(formJob.getRemark()); - existingJob.setTasks(formJob.getTasks()); existingJob.setPrice(formJob.getPrice()); } @@ -293,15 +280,6 @@ public class AddJobService { */ public Optional findCurrentDraft(String username) { List drafts = jobRepository.findByCreatedByAndIsDraftTrue(username); - return drafts.isEmpty() ? Optional.empty() : Optional.of(drafts.get(0)); - } - - /** - * Löscht alle Entwürfe eines Benutzers - */ - public void deleteUserDrafts(String username) { - List drafts = jobRepository.findByCreatedByAndIsDraftTrue(username); - jobRepository.deleteAll(drafts); - log.info("Entwürfe für Benutzer {} gelöscht", username); + return drafts.isEmpty() ? Optional.empty() : Optional.of(drafts.getFirst()); } } diff --git a/src/main/java/de/assecutor/votianlt/pages/add_job/ui/view/AddJobView.java b/src/main/java/de/assecutor/votianlt/pages/add_job/ui/view/AddJobView.java index 5d2acb2..a14c7ad 100644 --- a/src/main/java/de/assecutor/votianlt/pages/add_job/ui/view/AddJobView.java +++ b/src/main/java/de/assecutor/votianlt/pages/add_job/ui/view/AddJobView.java @@ -33,11 +33,16 @@ import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.theme.lumo.LumoUtility; import de.assecutor.votianlt.model.Job; +import de.assecutor.votianlt.model.TaskEntry; import de.assecutor.votianlt.pages.add_job.service.AddJobService; import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar; import jakarta.annotation.security.RolesAllowed; import lombok.extern.slf4j.Slf4j; +import de.assecutor.votianlt.model.CargoItem; +import java.util.*; +import java.util.Objects; +import de.assecutor.votianlt.model.TaskEntry; import java.util.Optional; @Route(value = "add_job", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class) @@ -100,11 +105,16 @@ public class AddJobView extends Main { // Submit button private Button submitButton; - // Transient transfer list for cargo items (not part of Job entity anymore) - private java.util.List jobTransientCargo; + // Backing list for cargo items to mirror UI rows + private final List cargoItemsState = new ArrayList<>(); // Stage sections for drag and drop + // Backing list for tasks to mirror UI rows + private final List tasksState = new ArrayList<>(); // Dynamic lists and additional controls + // Cargo section UI refs for error highlighting + private VerticalLayout cargoAreaContainer; + private Span cargoError; private VerticalLayout cargoList; private VerticalLayout tasksList; private TextArea remarkArea; @@ -647,13 +657,11 @@ public class AddJobView extends Main { binder.bind(pickupSalutation, Job::getPickupSalutation, Job::setPickupSalutation); binder.bind(pickupPhone, Job::getPickupPhone, Job::setPickupPhone); binder.bind(pickupAddressAddition, Job::getPickupAddressAddition, Job::setPickupAddressAddition); - binder.bind(savePickupAddress, Job::isSavePickupAddress, Job::setSavePickupAddress); binder.bind(deliveryCompany, Job::getDeliveryCompany, Job::setDeliveryCompany); binder.bind(deliverySalutation, Job::getDeliverySalutation, Job::setDeliverySalutation); binder.bind(deliveryPhone, Job::getDeliveryPhone, Job::setDeliveryPhone); binder.bind(deliveryAddressAddition, Job::getDeliveryAddressAddition, Job::setDeliveryAddressAddition); - binder.bind(saveDeliveryAddress, Job::isSaveDeliveryAddress, Job::setSaveDeliveryAddress); binder.bind(digitalProcessing, Job::isDigitalProcessing, Job::setDigitalProcessing); binder.bind(appUser, Job::getAppUser, Job::setAppUser); @@ -800,54 +808,33 @@ public class AddJobView extends Main { job.setPickupDate(pickupDate.getValue()); job.setDeliveryDate(deliveryDate.getValue()); if (remarkArea != null) job.setRemark(remarkArea.getValue()); - if (tasksList != null) { - java.util.List tasks = new java.util.ArrayList<>(); - tasksList.getChildren().forEach(comp -> { - if (comp instanceof com.vaadin.flow.component.orderedlayout.HorizontalLayout row) { - row.getChildren().filter(c -> c instanceof TextField).forEach(tf -> { - String v = ((TextField) tf).getValue(); - if (v != null && !v.trim().isEmpty()) tasks.add(v.trim()); - }); - } - }); - job.setTasks(tasks); - } - if (cargoList != null) { - java.util.List items = new java.util.ArrayList<>(); - cargoList.getChildren().forEach(comp -> { - if (comp instanceof com.vaadin.flow.component.orderedlayout.HorizontalLayout row) { - String desc = null; Integer qty = null; Double weight = null, len = null, wid = null, hei = null; - for (com.vaadin.flow.component.Component c : row.getChildren().toList()) { - if (c instanceof TextField tf && tf.getLabel() != null && tf.getLabel().contains("Beschreibung")) desc = tf.getValue(); - if (c instanceof IntegerField ifld) qty = ifld.getValue(); - if (c instanceof NumberField nf) { - String label = nf.getLabel(); - if (label != null) { - switch (label) { - case "Gewicht" -> weight = nf.getValue(); - case "Länge" -> len = nf.getValue(); - case "Breite" -> wid = nf.getValue(); - case "Höhe" -> hei = nf.getValue(); - } - } - } - } - if (desc != null || qty != null || weight != null || len != null || wid != null || hei != null) { - de.assecutor.votianlt.model.CargoItem ci = new de.assecutor.votianlt.model.CargoItem(); - ci.setDescription(desc); ci.setQuantity(qty); ci.setWeightKg(weight); - ci.setLengthMm(len); ci.setWidthMm(wid); ci.setHeightMm(hei); - items.add(ci); - } - } - }); - // temporär im Job-Objekt als Transfertyp beilegen (über transient Helper) - jobTransientCargo = items; - } // Validate all required fields using the binder if (binder.writeBeanIfValid(job)) { - // All validations passed, save the job with cargo items - Job savedJob = addJobService.addJobWithCargo(job, jobTransientCargo); + // Ensure at least one cargo item is provided (tasks may be empty) + // Definition: Ein Cargo-Item gilt nur als gefüllt, wenn eine Beschreibung vorhanden ist + List cargoFilled = cargoItemsState.stream() + .filter(Objects::nonNull) + .filter(ci -> ci.getDescription() != null && !ci.getDescription().isBlank()) + .toList(); + + if (cargoFilled.isEmpty()) { + Notification errorNotification = Notification.show( + "Bitte fügen Sie mindestens eine Ladungszeile hinzu."); + errorNotification.setDuration(5000); + return; + } + // toggle cargo error highlight + boolean hasCargo = !cargoFilled.isEmpty(); + cargoError.setVisible(!hasCargo); + if (!hasCargo) { + cargoAreaContainer.getStyle().set("border", "1px solid var(--lumo-error-color-50pct)"); + } else { + cargoAreaContainer.getStyle().set("border", "1px solid var(--lumo-contrast-20pct)"); + } + + // All validations passed, save the job with cargo items and tasks (tasks may be empty) + Job savedJob = addJobService.addJobWithCargo(job, cargoFilled, tasksState); // Erfolgsmeldung anzeigen Notification successNotification = Notification.show( @@ -865,6 +852,9 @@ public class AddJobView extends Main { } catch (Exception e) { // Other errors + // Reset cargo error + if (cargoError != null) cargoError.setVisible(false); + if (cargoAreaContainer != null) cargoAreaContainer.getStyle().set("border", "1px solid var(--lumo-contrast-20pct)"); Notification errorNotification = Notification.show( "Fehler beim Erstellen des Auftrags: " + e.getMessage()); errorNotification.setDuration(5000); @@ -872,11 +862,19 @@ public class AddJobView extends Main { } /** + cargoItemsState.clear(); + cargoList.removeAll(); * Setzt alle Formularfelder zurück */ private void clearForm() { + // Reset cargo state and UI + cargoItemsState.clear(); + if (cargoList != null) cargoList.removeAll(); // Reset binder to clear validation state binder.readBean(new Job()); + // Reset tasks state and UI + tasksState.clear(); + if (tasksList != null) tasksList.removeAll(); // Customer selection customerSelection.clear(); @@ -937,7 +935,6 @@ public class AddJobView extends Main { job.setPickupAddressAddition(pickupAddressAddition.getValue()); job.setPickupZip(pickupZip.getValue()); job.setPickupCity(pickupCity.getValue()); - job.setSavePickupAddress(savePickupAddress.getValue()); // Delivery address job.setDeliveryCompany(deliveryCompany.getValue()); @@ -950,7 +947,6 @@ public class AddJobView extends Main { job.setDeliveryAddressAddition(deliveryAddressAddition.getValue()); job.setDeliveryZip(deliveryZip.getValue()); job.setDeliveryCity(deliveryCity.getValue()); - job.setSaveDeliveryAddress(saveDeliveryAddress.getValue()); // Digital processing job.setDigitalProcessing(digitalProcessing.getValue()); @@ -1015,28 +1011,32 @@ public class AddJobView extends Main { wrapper.setWidthFull(); wrapper.setSpacing(true); - VerticalLayout cargoArea = new VerticalLayout(); - cargoArea.setWidthFull(); - cargoArea.setSpacing(true); - cargoArea.getStyle().set("background", "var(--lumo-base-color)"); - cargoArea.getStyle().set("border", "1px solid var(--lumo-contrast-20pct)"); - cargoArea.getStyle().set("border-radius", "var(--lumo-border-radius-m)"); - cargoArea.getStyle().set("padding", "var(--lumo-space-m)"); + cargoAreaContainer = new VerticalLayout(); + cargoAreaContainer.setWidthFull(); + cargoAreaContainer.setSpacing(true); + cargoAreaContainer.getStyle().set("background", "var(--lumo-base-color)"); + cargoAreaContainer.getStyle().set("border", "1px solid var(--lumo-contrast-20pct)"); + cargoAreaContainer.getStyle().set("border-radius", "var(--lumo-border-radius-m)"); + cargoAreaContainer.getStyle().set("padding", "var(--lumo-space-m)"); - wrapper.add(new H3("Ladung")); + H3 cargoTitle = new H3("Ladung"); + cargoError = new Span("Bitte fügen Sie mindestens eine Ladungszeile hinzu."); + cargoError.getStyle().set("color", "var(--lumo-error-text-color)"); + cargoError.getStyle().set("font-size", "var(--lumo-font-size-s)"); + cargoError.setVisible(false); + + wrapper.add(cargoTitle); cargoList = new VerticalLayout(); cargoList.setPadding(false); cargoList.setSpacing(true); - cargoArea.add(cargoList); + cargoAreaContainer.add(cargoError, cargoList); java.util.function.BiConsumer> addCargoRow = (iconName, afterCreate) -> { HorizontalLayout row = new HorizontalLayout(); row.setWidthFull(); row.setAlignItems(FlexComponent.Alignment.END); - - ComboBox desc = new ComboBox<>("Beschreibung"); desc.setItems("Europalette", "Einwegpalette", "Düsseldorfer-Palette", "Gitterboxpalette", "Gitterwagen", "Paket"); desc.setAllowCustomValue(true); @@ -1064,10 +1064,43 @@ public class AddJobView extends Main { Button remove = new Button(new Icon(VaadinIcon.CLOSE_SMALL)); remove.addThemeVariants(ButtonVariant.LUMO_ERROR, ButtonVariant.LUMO_TERTIARY); - remove.addClickListener(e -> cargoList.remove(row)); + remove.addClickListener(e -> { + int idx = cargoList.getChildren().toList().indexOf(row); + if (idx >= 0 && idx < cargoItemsState.size()) { + cargoItemsState.remove(idx); + } + cargoList.remove(row); + }); row.add(desc, qty, weight, len, wid, hei, remove); cargoList.add(row); + + // Ensure backing list is in sync: add new item and bind change listeners + CargoItem item = new CargoItem(); + cargoItemsState.add(item); + + // Pre-fill current input values into backing item + item.setDescription(desc.getValue()); + item.setQuantity(qty.getValue()); + item.setWeightKg(weight.getValue()); + item.setLengthMm(len.getValue()); + // Initialize from current inputs + item.setDescription(desc.getValue()); + item.setQuantity(qty.getValue()); + item.setWeightKg(weight.getValue()); + item.setLengthMm(len.getValue()); + item.setWidthMm(wid.getValue()); + item.setHeightMm(hei.getValue()); + item.setWidthMm(wid.getValue()); + item.setHeightMm(hei.getValue()); + + desc.addValueChangeListener(ev -> item.setDescription(ev.getValue())); + qty.addValueChangeListener(ev -> item.setQuantity(ev.getValue())); + weight.addValueChangeListener(ev -> item.setWeightKg(ev.getValue())); + len.addValueChangeListener(ev -> item.setLengthMm(ev.getValue())); + wid.addValueChangeListener(ev -> item.setWidthMm(ev.getValue())); + hei.addValueChangeListener(ev -> item.setHeightMm(ev.getValue())); + if (afterCreate != null) afterCreate.accept(row); }; @@ -1075,42 +1108,10 @@ public class AddJobView extends Main { addCargoRow.accept("paket", r -> {}); addCargoRow.accept("", r -> {}); - wrapper.add(cargoArea); + wrapper.add(cargoAreaContainer); return wrapper; } - private void populateFromJob(Job job) { - // Pickup address - if (job.getPickupCompany() != null) pickupCompany.setValue(job.getPickupCompany()); - if (job.getPickupSalutation() != null) pickupSalutation.setValue(job.getPickupSalutation()); - if (job.getPickupFirstName() != null) pickupFirstName.setValue(job.getPickupFirstName()); - if (job.getPickupLastName() != null) pickupLastName.setValue(job.getPickupLastName()); - if (job.getPickupPhone() != null) pickupPhone.setValue(job.getPickupPhone()); - if (job.getPickupStreet() != null) pickupStreet.setValue(job.getPickupStreet()); - if (job.getPickupHouseNumber() != null) pickupHouseNumber.setValue(job.getPickupHouseNumber()); - if (job.getPickupAddressAddition() != null) pickupAddressAddition.setValue(job.getPickupAddressAddition()); - if (job.getPickupZip() != null) pickupZip.setValue(job.getPickupZip()); - if (job.getPickupCity() != null) pickupCity.setValue(job.getPickupCity()); - savePickupAddress.setValue(job.isSavePickupAddress()); - - // Delivery address - if (job.getDeliveryCompany() != null) deliveryCompany.setValue(job.getDeliveryCompany()); - if (job.getDeliverySalutation() != null) deliverySalutation.setValue(job.getDeliverySalutation()); - if (job.getDeliveryFirstName() != null) deliveryFirstName.setValue(job.getDeliveryFirstName()); - if (job.getDeliveryLastName() != null) deliveryLastName.setValue(job.getDeliveryLastName()); - if (job.getDeliveryPhone() != null) deliveryPhone.setValue(job.getDeliveryPhone()); - if (job.getDeliveryStreet() != null) deliveryStreet.setValue(job.getDeliveryStreet()); - if (job.getDeliveryHouseNumber() != null) deliveryHouseNumber.setValue(job.getDeliveryHouseNumber()); - if (job.getDeliveryAddressAddition() != null) deliveryAddressAddition.setValue(job.getDeliveryAddressAddition()); - if (job.getDeliveryZip() != null) deliveryZip.setValue(job.getDeliveryZip()); - if (job.getDeliveryCity() != null) deliveryCity.setValue(job.getDeliveryCity()); - saveDeliveryAddress.setValue(job.isSaveDeliveryAddress()); - - // Digital processing - digitalProcessing.setValue(job.isDigitalProcessing()); - if (job.getAppUser() != null) appUser.setValue(job.getAppUser()); - } - private Component createTasksAndNotesSection() { VerticalLayout wrapper = new VerticalLayout(); wrapper.setWidthFull(); @@ -1144,11 +1145,21 @@ public class AddJobView extends Main { Button remove = new Button(new Icon(VaadinIcon.CLOSE_SMALL)); remove.addThemeVariants(ButtonVariant.LUMO_ERROR, ButtonVariant.LUMO_TERTIARY); - remove.addClickListener(e -> tasksList.remove(row)); + remove.addClickListener(e -> { + int idx = tasksList.getChildren().toList().indexOf(row); + if (idx >= 0 && idx < tasksState.size()) tasksState.remove(idx); + tasksList.remove(row); + }); row.add(taskField, remove); row.setFlexGrow(1, taskField); tasksList.add(row); + + // Keep backing tasks list in sync + TaskEntry te = new TaskEntry(); + te.setText(taskField.getValue()); + tasksState.add(te); + taskField.addValueChangeListener(ev -> te.setText(ev.getValue())); }; // 1 Beispielzeile diff --git a/src/main/java/de/assecutor/votianlt/repository/TaskRepository.java b/src/main/java/de/assecutor/votianlt/repository/TaskRepository.java new file mode 100644 index 0000000..b8d3bad --- /dev/null +++ b/src/main/java/de/assecutor/votianlt/repository/TaskRepository.java @@ -0,0 +1,12 @@ +package de.assecutor.votianlt.repository; + +import de.assecutor.votianlt.model.TaskEntry; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.repository.MongoRepository; + +import java.util.List; + +public interface TaskRepository extends MongoRepository { + List findByJobId(ObjectId jobId); +} +