Erweiterungen

This commit is contained in:
2025-09-09 20:03:07 +02:00
parent 8ecd05b3c0
commit 32334657f5
5 changed files with 186 additions and 21 deletions

View File

@@ -6,7 +6,6 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.index.Indexed;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Set;
@@ -18,28 +17,29 @@ public class User {
private ObjectId id;
private int usrId;
private int hqId;
private short type;
private String title;
private String name;
private String firstname;
private LocalDate birthdate;
private String name; // Nachname
private String firstname; // Vorname
// Firmen-/Adressdaten
private String company; // Firma
private String street; // Straße
private String houseNumber; // Hausnr
private String addressAddition; // Adresszusatz (optional)
private String zip; // Postleitzahl
private String city; // Stadt
@Indexed(unique = true)
private String email;
private String invitationEmail;
private String phone;
private String phone2;
private String fax;
private String password;
private byte isActivated;
private String activationCode;
private byte isEmailConfirmed;
private byte isPasswordLost;
private String passwordCode;
private LocalDateTime passwordTimestamp;
private LocalDateTime activationDate;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private Set<String> roles;

View File

@@ -40,7 +40,7 @@ public class AddJobService {
job.setCreatedAt(now);
job.setUpdatedAt(now);
job.setStatus(JobStatus.CREATED);
job.setCreatedBy(securityService.getCurrentUsername());
job.setCreatedBy(securityService.getCurrentUserId().toHexString());
// Auftragsnummer generieren, falls nicht vorhanden
if (job.getJobNumber() == null || job.getJobNumber().isEmpty()) {

View File

@@ -7,6 +7,8 @@ import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.textfield.PasswordField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.PageTitle;
@@ -31,6 +33,17 @@ public class RegisterView extends VerticalLayout {
private TextField emailField;
private PasswordField passwordField;
private PasswordField confirmPasswordField;
// Zusätzliche Pflichtfelder aus EditProfileView
private TextField firstNameField;
private TextField lastNameField;
private TextField phoneField;
private TextField companyField;
private TextField streetField;
private TextField houseNumberField;
private TextField zipField;
private TextField cityField;
private TextField codeField;
private Button submitButton;
private Button verifyButton;
@@ -58,7 +71,7 @@ public class RegisterView extends VerticalLayout {
private VerticalLayout createFormContainer() {
VerticalLayout container = new VerticalLayout();
container.setWidth("400px");
container.setWidth("980px");
container.setPadding(true);
container.setSpacing(true);
container.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.STRETCH);
@@ -98,6 +111,32 @@ public class RegisterView extends VerticalLayout {
confirmPasswordField.setRequired(true);
confirmPasswordField.setPlaceholder("Passwort wiederholen");
// Pflichtfelder aus EditProfileView
firstNameField = new TextField("Vorname");
firstNameField.setWidthFull();
firstNameField.setRequired(true);
lastNameField = new TextField("Nachname");
lastNameField.setWidthFull();
lastNameField.setRequired(true);
phoneField = new TextField("Telefonnummer");
phoneField.setWidthFull();
phoneField.setRequired(true);
companyField = new TextField("Firma");
companyField.setWidthFull();
companyField.setRequired(true);
streetField = new TextField("Straße");
streetField.setWidthFull();
streetField.setRequired(true);
houseNumberField = new TextField("Hausnr");
houseNumberField.setWidthFull();
houseNumberField.setRequired(true);
zipField = new TextField("Postleitzahl");
zipField.setWidthFull();
zipField.setRequired(true);
cityField = new TextField("Stadt");
cityField.setWidthFull();
cityField.setRequired(true);
codeField = new TextField("Bestätigungscode (6 Ziffern)");
codeField.setWidthFull();
codeField.setMaxLength(6);
@@ -132,8 +171,43 @@ public class RegisterView extends VerticalLayout {
backButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
backButton.setWidthFull();
container.add(title, subtitle, emailField, passwordField, confirmPasswordField,
submitButton, codeField, verifyButton, resendButton, backButton);
// Zweispaltiges Formular
FormLayout form = new FormLayout();
form.setWidthFull();
form.setResponsiveSteps(
new FormLayout.ResponsiveStep("0", 2)
);
// Erste Reihe: Zugangsdaten
form.add(emailField, passwordField, confirmPasswordField);
form.setColspan(emailField, 2);
// Personen-/Firmendaten
form.add(firstNameField, lastNameField);
form.add(phoneField, companyField);
form.add(streetField, houseNumberField);
form.add(zipField, cityField);
// Code und Verifikations-Buttons (ausgeblendet bis Versand)
form.add(codeField);
form.setColspan(codeField, 2);
// Button-Zeile: Verifizieren/Resenden nebeneinander
HorizontalLayout verifyRow = new HorizontalLayout(verifyButton, resendButton);
verifyRow.setWidthFull();
verifyRow.setSpacing(true);
verifyRow.setAlignItems(FlexComponent.Alignment.STRETCH);
verifyRow.setFlexGrow(1, verifyButton, resendButton);
form.add(verifyRow);
form.setColspan(verifyRow, 2);
// Haupt-Submit-Button und Zurück-Link über volle Breite
form.add(submitButton);
form.setColspan(submitButton, 2);
form.add(backButton);
form.setColspan(backButton, 2);
container.add(title, subtitle, form);
return container;
}
@@ -173,6 +247,56 @@ public class RegisterView extends VerticalLayout {
return;
}
// Weitere Pflichtfelder prüfen (aus Edit-Profile)
var firstName = firstNameField.getValue() != null ? firstNameField.getValue().trim() : "";
if (firstName.isEmpty()) {
Notification.show("Bitte geben Sie Ihren Vornamen ein.", 3000, Notification.Position.MIDDLE);
firstNameField.focus();
return;
}
var lastName = lastNameField.getValue() != null ? lastNameField.getValue().trim() : "";
if (lastName.isEmpty()) {
Notification.show("Bitte geben Sie Ihren Nachnamen ein.", 3000, Notification.Position.MIDDLE);
lastNameField.focus();
return;
}
var phone = phoneField.getValue() != null ? phoneField.getValue().trim() : "";
if (phone.isEmpty()) {
Notification.show("Bitte geben Sie Ihre Telefonnummer ein.", 3000, Notification.Position.MIDDLE);
phoneField.focus();
return;
}
var company = companyField.getValue() != null ? companyField.getValue().trim() : "";
if (company.isEmpty()) {
Notification.show("Bitte geben Sie den Firmennamen ein.", 3000, Notification.Position.MIDDLE);
companyField.focus();
return;
}
var street = streetField.getValue() != null ? streetField.getValue().trim() : "";
if (street.isEmpty()) {
Notification.show("Bitte geben Sie die Straße ein.", 3000, Notification.Position.MIDDLE);
streetField.focus();
return;
}
var houseNo = houseNumberField.getValue() != null ? houseNumberField.getValue().trim() : "";
if (houseNo.isEmpty()) {
Notification.show("Bitte geben Sie die Hausnummer ein.", 3000, Notification.Position.MIDDLE);
houseNumberField.focus();
return;
}
var zip = zipField.getValue() != null ? zipField.getValue().trim() : "";
if (zip.isEmpty()) {
Notification.show("Bitte geben Sie die Postleitzahl ein.", 3000, Notification.Position.MIDDLE);
zipField.focus();
return;
}
var city = cityField.getValue() != null ? cityField.getValue().trim() : "";
if (city.isEmpty()) {
Notification.show("Bitte geben Sie die Stadt ein.", 3000, Notification.Position.MIDDLE);
cityField.focus();
return;
}
// Alles ok: Code erzeugen und senden
sendVerificationCode(email);
}
@@ -205,6 +329,17 @@ public class RegisterView extends VerticalLayout {
emailField.setReadOnly(true);
passwordField.setReadOnly(true);
confirmPasswordField.setReadOnly(true);
// Zusätzliche Felder sperren
firstNameField.setReadOnly(true);
lastNameField.setReadOnly(true);
phoneField.setReadOnly(true);
companyField.setReadOnly(true);
streetField.setReadOnly(true);
houseNumberField.setReadOnly(true);
zipField.setReadOnly(true);
cityField.setReadOnly(true);
submitButton.setEnabled(false);
Notification.show("Ein Bestätigungscode wurde an " + email + " gesendet.", 4000, Notification.Position.MIDDLE);
@@ -236,8 +371,24 @@ public class RegisterView extends VerticalLayout {
// Code korrekt -> Benutzer erstellen
var email = emailField.getValue().trim();
var password = passwordField.getValue();
var firstName = firstNameField.getValue() != null ? firstNameField.getValue().trim() : "";
var lastName = lastNameField.getValue() != null ? lastNameField.getValue().trim() : "";
var phone = phoneField.getValue() != null ? phoneField.getValue().trim() : "";
try {
userService.createUser(email, password, "Benutzer", "Name");
var user = userService.createUser(email, password, firstName, lastName);
// Persistiere zusätzliche Profil-/Adressdaten
if (!phone.isBlank()) user.setPhone(phone);
var company = companyField.getValue() != null ? companyField.getValue().trim() : null;
var street = streetField.getValue() != null ? streetField.getValue().trim() : null;
var houseNo = houseNumberField.getValue() != null ? houseNumberField.getValue().trim() : null;
var zip = zipField.getValue() != null ? zipField.getValue().trim() : null;
var city = cityField.getValue() != null ? cityField.getValue().trim() : null;
user.setCompany(company);
user.setStreet(street);
user.setHouseNumber(houseNo);
user.setZip(zip);
user.setCity(city);
userService.save(user);
VaadinSession.getCurrent().setAttribute("flashMessage", "Registrierung erfolgreich. Bitte melden Sie sich an.");
getUI().ifPresent(ui -> ui.navigate("login"));
} catch (RuntimeException e) {

View File

@@ -11,6 +11,7 @@ import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.model.Customer;
import de.assecutor.votianlt.pages.service.CustomerService;
import de.assecutor.votianlt.security.SecurityService;
import jakarta.annotation.security.RolesAllowed;
import org.springframework.beans.factory.annotation.Autowired;
@@ -20,11 +21,13 @@ import org.springframework.beans.factory.annotation.Autowired;
public class ShowCustomersView extends VerticalLayout {
private final CustomerService customerService;
private final SecurityService securityService;
private final Grid<Customer> grid = new Grid<>(Customer.class, false);
@Autowired
public ShowCustomersView(CustomerService customerService) {
public ShowCustomersView(CustomerService customerService, SecurityService securityService) {
this.customerService = customerService;
this.securityService = securityService;
setSizeFull();
setPadding(true);
setSpacing(true);
@@ -86,6 +89,10 @@ public class ShowCustomersView extends VerticalLayout {
private void loadData() {
var customers = customerService.findAll();
grid.setItems(customers);
var currentUserId = securityService.getCurrentUserId();
var ownCustomers = customers.stream()
.filter(c -> c.getCreatedBy() != null && c.getCreatedBy().equals(currentUserId))
.toList();
grid.setItems(ownCustomers);
}
}

View File

@@ -13,6 +13,7 @@ import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.model.Job;
import de.assecutor.votianlt.model.JobStatus;
import de.assecutor.votianlt.repository.JobRepository;
import de.assecutor.votianlt.security.SecurityService;
import jakarta.annotation.security.RolesAllowed;
import org.springframework.beans.factory.annotation.Autowired;
@@ -24,11 +25,13 @@ public class ShowJobsView extends VerticalLayout {
private final DatePicker startDate = new DatePicker("Startdatum");
private final DatePicker endDate = new DatePicker("Enddatum");
private final JobRepository jobRepository;
private final SecurityService securityService;
private final Grid<Job> grid = new Grid<>(Job.class, false);
@Autowired
public ShowJobsView(JobRepository jobRepository) {
public ShowJobsView(JobRepository jobRepository, SecurityService securityService) {
this.jobRepository = jobRepository;
this.securityService = securityService;
setSizeFull();
setPadding(true);
setSpacing(true);
@@ -88,16 +91,20 @@ public class ShowJobsView extends VerticalLayout {
java.time.LocalDateTime startDt = start != null ? start.atStartOfDay() : java.time.LocalDate.now().minusDays(30).atStartOfDay();
java.time.LocalDateTime endDt = end != null ? end.atTime(23,59,59) : java.time.LocalDate.now().atTime(23,59,59);
// Hole Aufträge im Zeitraum und filtere auf offene Status
// Aktuellen Benutzer (ObjectId Hex) ermitteln
String currentUserIdHex = securityService.getCurrentUserId().toHexString();
// Hole Aufträge im Zeitraum, filtere auf offenen Status und auf den angemeldeten Benutzer
var inRange = jobRepository.findByCreatedAtBetween(startDt, endDt);
var open = inRange.stream()
var openAndOwn = inRange.stream()
.filter(j -> j.getStatus() == JobStatus.CREATED
|| j.getStatus() == JobStatus.IN_PROGRESS
|| j.getStatus() == JobStatus.PICKUP_SCHEDULED
|| j.getStatus() == JobStatus.PICKED_UP
|| j.getStatus() == JobStatus.IN_TRANSIT)
.filter(j -> j.getCreatedBy() != null && j.getCreatedBy().equals(currentUserIdHex))
.toList();
grid.setItems(open);
grid.setItems(openAndOwn);
}
private void exportToCsv() {