Harden staff assignment

This commit is contained in:
2026-04-05 12:17:37 -06:00
parent 072c9aadea
commit 5d95613786
33 changed files with 887 additions and 30 deletions

View File

@@ -15,6 +15,8 @@ public class AppointmentDTO {
private SimpleIntegerProperty serviceId;
private SimpleStringProperty serviceName;
private SimpleIntegerProperty employeeId;
private SimpleStringProperty employeeName;
private SimpleStringProperty appointmentDate;
private SimpleStringProperty appointmentTime;
@@ -25,6 +27,8 @@ public class AppointmentDTO {
int customerId, String customerName,
int petId, String petName,
int serviceId, String serviceName,
int employeeId,
String employeeName,
String appointmentDate,
String appointmentTime,
String appointmentStatus) {
@@ -36,6 +40,8 @@ public class AppointmentDTO {
this.petName = new SimpleStringProperty(petName);
this.serviceId = new SimpleIntegerProperty(serviceId);
this.serviceName = new SimpleStringProperty(serviceName);
this.employeeId = new SimpleIntegerProperty(employeeId);
this.employeeName = new SimpleStringProperty(employeeName);
this.appointmentDate = new SimpleStringProperty(appointmentDate);
this.appointmentTime = new SimpleStringProperty(appointmentTime);
this.appointmentStatus = new SimpleStringProperty(appointmentStatus);
@@ -52,8 +58,10 @@ public class AppointmentDTO {
public int getServiceId() { return serviceId.get(); }
public String getServiceName() { return serviceName.get(); }
public int getEmployeeId() { return employeeId.get(); }
public String getEmployeeName() { return employeeName.get(); }
public String getAppointmentDate() { return appointmentDate.get(); }
public String getAppointmentTime() { return appointmentTime.get(); }
public String getAppointmentStatus() { return appointmentStatus.get(); }
}
}

View File

@@ -5,6 +5,7 @@ import java.time.LocalDate;
public class AdoptionRequest {
private Long petId;
private Long customerId;
private Long employeeId;
private LocalDate adoptionDate;
private String adoptionStatus;
@@ -27,6 +28,14 @@ public class AdoptionRequest {
this.customerId = customerId;
}
public Long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Long employeeId) {
this.employeeId = employeeId;
}
public LocalDate getAdoptionDate() {
return adoptionDate;
}

View File

@@ -6,8 +6,10 @@ public class AdoptionResponse {
private Long adoptionId;
private Long petId;
private Long customerId;
private Long employeeId;
private String petName;
private String customerName;
private String employeeName;
private LocalDate adoptionDate;
private java.math.BigDecimal adoptionFee;
private String adoptionStatus;
@@ -39,6 +41,14 @@ public class AdoptionResponse {
this.customerId = customerId;
}
public Long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Long employeeId) {
this.employeeId = employeeId;
}
public String getPetName() {
return petName;
}
@@ -55,6 +65,14 @@ public class AdoptionResponse {
this.customerName = customerName;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public LocalDate getAdoptionDate() {
return adoptionDate;
}

View File

@@ -10,6 +10,7 @@ public class AppointmentRequest {
private Long customerId;
private Long storeId;
private Long serviceId;
private Long employeeId;
private LocalDate appointmentDate;
private LocalTime appointmentTime;
private String appointmentStatus;
@@ -57,6 +58,14 @@ public class AppointmentRequest {
this.serviceId = serviceId;
}
public Long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Long employeeId) {
this.employeeId = employeeId;
}
public LocalDate getAppointmentDate() {
return appointmentDate;
}

View File

@@ -15,6 +15,8 @@ public class AppointmentResponse {
private java.util.List<String> customerPetNames;
private java.util.List<Long> customerPetIds;
private String serviceName;
private Long employeeId;
private String employeeName;
private LocalDate appointmentDate;
private LocalTime appointmentTime;
private String appointmentStatus;
@@ -110,6 +112,22 @@ public class AppointmentResponse {
this.serviceName = serviceName;
}
public Long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Long employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public LocalDate getAppointmentDate() {
return appointmentDate;
}

View File

@@ -97,4 +97,12 @@ public class DropdownApi {
}
return apiClient.getObjectMapper().readValue(response, new TypeReference<List<DropdownOption>>() {});
}
public List<DropdownOption> getStoreEmployees(Long storeId) throws Exception {
String response = apiClient.getRawResponse("/api/v1/dropdowns/stores/" + storeId + "/employees");
if (response == null || response.isEmpty()) {
throw new IllegalStateException("Empty response from store employees endpoint");
}
return apiClient.getObjectMapper().readValue(response, new TypeReference<List<DropdownOption>>() {});
}
}

View File

@@ -43,6 +43,9 @@ public class AdoptionController {
@FXML
private TableColumn<Adoption, String> colCustomerName;
@FXML
private TableColumn<Adoption, String> colEmployeeName;
@FXML
private TableColumn<Adoption, String> colAdoptionDate;
@@ -71,6 +74,7 @@ public class AdoptionController {
colAdoptionId.setCellValueFactory(new PropertyValueFactory<>("adoptionId"));
colPetId.setCellValueFactory(new PropertyValueFactory<>("petName"));
colCustomerName.setCellValueFactory(new PropertyValueFactory<>("customerName"));
colEmployeeName.setCellValueFactory(new PropertyValueFactory<>("employeeName"));
colAdoptionDate.setCellValueFactory(new PropertyValueFactory<>("adoptionDate"));
colAdoptionFee.setCellValueFactory(new PropertyValueFactory<>("adoptionFee"));
colAdoptionStatus.setCellValueFactory(new PropertyValueFactory<>("adoptionStatus"));
@@ -252,8 +256,10 @@ public class AdoptionController {
response.getAdoptionId().intValue(),
response.getPetId() != null ? response.getPetId().intValue() : 0,
response.getCustomerId() != null ? response.getCustomerId().intValue() : 0,
response.getEmployeeId() != null ? response.getEmployeeId().intValue() : 0,
response.getPetName(),
response.getCustomerName(),
response.getEmployeeName(),
response.getAdoptionDate() != null ? response.getAdoptionDate().toString() : "",
response.getAdoptionFee() != null ? response.getAdoptionFee().doubleValue() : 0.0,
response.getAdoptionStatus()

View File

@@ -33,6 +33,7 @@ public class AppointmentController {
@FXML private TableColumn<AppointmentDTO,String> colAppointmentDate;
@FXML private TableColumn<AppointmentDTO,String> colAppointmentTime;
@FXML private TableColumn<AppointmentDTO,String> colCustomerName;
@FXML private TableColumn<AppointmentDTO,String> colEmployeeName;
@FXML private TableColumn<AppointmentDTO,String> colAppointmentStatus;
@FXML private Button btnAdd;
@@ -55,6 +56,7 @@ public class AppointmentController {
colAppointmentDate.setCellValueFactory(new PropertyValueFactory<>("appointmentDate"));
colAppointmentTime.setCellValueFactory(new PropertyValueFactory<>("appointmentTime"));
colCustomerName.setCellValueFactory(new PropertyValueFactory<>("customerName"));
colEmployeeName.setCellValueFactory(new PropertyValueFactory<>("employeeName"));
colAppointmentStatus.setCellValueFactory(new PropertyValueFactory<>("appointmentStatus"));
filtered = new FilteredList<>(appointments, a -> true);
@@ -247,6 +249,8 @@ public class AppointmentController {
petName,
response.getServiceId() != null ? response.getServiceId().intValue() : 0,
response.getServiceName(),
response.getEmployeeId() != null ? response.getEmployeeId().intValue() : 0,
response.getEmployeeName(),
response.getAppointmentDate().toString(),
response.getAppointmentTime().toString(),
response.getAppointmentStatus()

View File

@@ -11,6 +11,7 @@ import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
import org.example.petshopdesktop.api.dto.adoption.AdoptionRequest;
@@ -38,6 +39,9 @@ public class AdoptionDialogController {
@FXML
private ComboBox<DropdownOption> cbCustomer;
@FXML
private ComboBox<DropdownOption> cbEmployee;
@FXML
private ComboBox<DropdownOption> cbPet;
@@ -62,6 +66,7 @@ public class AdoptionDialogController {
void initialize() {
cbAdoptionStatus.setItems(statusList);
cbEmployee.setPromptText("Select an employee");
new Thread(() -> {
try {
@@ -83,6 +88,38 @@ public class AdoptionDialogController {
}
}).start();
new Thread(() -> {
try {
Long storeId = org.example.petshopdesktop.auth.UserSession.getInstance().getStoreId();
List<DropdownOption> employees = storeId != null && storeId > 0 ? DropdownApi.getInstance().getStoreEmployees(storeId) : List.of();
Platform.runLater(() -> cbEmployee.setItems(FXCollections.observableArrayList(employees)));
} catch (Exception e) {
Platform.runLater(() -> {
ActivityLogger.getInstance().logException(
"AdoptionDialogController.initialize",
e,
"Loading employees for combo box");
cbEmployee.setDisable(true);
cbEmployee.setPromptText("Unable to load employees");
});
}
}).start();
cbEmployee.setCellFactory(param -> new ListCell<>() {
@Override
protected void updateItem(DropdownOption option, boolean empty) {
super.updateItem(option, empty);
setText(empty || option == null ? null : option.getLabel());
}
});
cbEmployee.setButtonCell(new ListCell<>() {
@Override
protected void updateItem(DropdownOption option, boolean empty) {
super.updateItem(option, empty);
setText(empty || option == null ? null : option.getLabel());
}
});
new Thread(() -> {
try {
List<DropdownOption> customers = DropdownApi.getInstance().getCustomers();
@@ -129,6 +166,10 @@ public class AdoptionDialogController {
errorMsg += "Customer is required.\n";
}
if (cbEmployee.getSelectionModel().getSelectedItem() == null) {
errorMsg += "Employee is required.\n";
}
if (dpAdoptionDate.getValue() == null) {
errorMsg += "Adoption Date is required.\n";
}
@@ -142,6 +183,7 @@ public class AdoptionDialogController {
AdoptionRequest request = new AdoptionRequest();
request.setPetId(cbPet.getSelectionModel().getSelectedItem().getId());
request.setCustomerId(cbCustomer.getSelectionModel().getSelectedItem().getId());
request.setEmployeeId(cbEmployee.getSelectionModel().getSelectedItem().getId());
request.setAdoptionDate(dpAdoptionDate.getValue());
request.setAdoptionStatus(cbAdoptionStatus.getValue());
@@ -204,6 +246,15 @@ public class AdoptionDialogController {
}
}
if (adoption.getEmployeeId() > 0) {
for (DropdownOption employee : cbEmployee.getItems()) {
if (employee.getId() != null && employee.getId().equals(adoption.getEmployeeId())) {
cbEmployee.getSelectionModel().select(employee);
break;
}
}
}
if (adoption.getAdoptionDate() != null && !adoption.getAdoptionDate().isEmpty()) {
try {
dpAdoptionDate.setValue(LocalDate.parse(adoption.getAdoptionDate()));

View File

@@ -35,6 +35,7 @@ public class AppointmentDialogController {
@FXML private ComboBox<DropdownOption> cbService;
@FXML private ComboBox<DropdownOption> cbCustomer;
@FXML private ComboBox<DropdownOption> cbPet;
@FXML private ComboBox<DropdownOption> cbEmployee;
@FXML private ComboBox<Integer> cbHour;
@FXML private ComboBox<Integer> cbMinute;
@@ -94,14 +95,32 @@ public class AppointmentDialogController {
ActivityLogger.getInstance().logException(
"AppointmentDialogController.initialize",
e,
"Loading combo box data for services, customers, and pets");
"Loading services/customers for appointment dialog");
e.printStackTrace();
});
}
}).start();
new Thread(() -> {
try {
Long storeId = UserSession.getInstance().getStoreId();
List<DropdownOption> employees = storeId != null && storeId > 0 ? DropdownApi.getInstance().getStoreEmployees(storeId) : List.of();
Platform.runLater(() -> cbEmployee.setItems(FXCollections.observableArrayList(employees)));
} catch (Exception e) {
Platform.runLater(() -> {
ActivityLogger.getInstance().logException(
"AppointmentDialogController.initialize",
e,
"Loading employees for appointment dialog");
cbEmployee.setDisable(true);
cbEmployee.setPromptText("Unable to load employees");
});
}
}).start();
cbAppointmentStatus.setItems(statusList);
cbPet.setDisable(true);
cbEmployee.setPromptText("Select an employee");
cbPet.setPromptText("Select a customer first");
cbCustomer.setPromptText("Select a customer");
cbService.setPromptText("Select a service");
@@ -161,6 +180,21 @@ public class AppointmentDialogController {
}
});
cbEmployee.setCellFactory(param -> new ListCell<>() {
@Override
protected void updateItem(DropdownOption option, boolean empty) {
super.updateItem(option, empty);
setText(empty || option == null ? null : option.getLabel());
}
});
cbEmployee.setButtonCell(new ListCell<>() {
@Override
protected void updateItem(DropdownOption option, boolean empty) {
super.updateItem(option, empty);
setText(empty || option == null ? null : option.getLabel());
}
});
cbCustomer.valueProperty().addListener((obs, oldValue, newValue) -> {
Long customerId = newValue != null ? newValue.getId() : null;
cbPet.setValue(null);
@@ -222,6 +256,14 @@ public class AppointmentDialogController {
cbCustomer.setValue(c);
}
});
if (appt.getEmployeeId() > 0) {
cbEmployee.getItems().forEach(employee -> {
if (employee.getId() != null && employee.getId().longValue() == appt.getEmployeeId()) {
cbEmployee.setValue(employee);
}
});
}
}
//
@@ -233,6 +275,7 @@ public class AppointmentDialogController {
if (cbService.getValue() == null ||
cbCustomer.getValue() == null ||
cbPet.getValue() == null ||
cbEmployee.getValue() == null ||
dpAppointmentDate.getValue() == null ||
cbHour.getValue() == null ||
cbMinute.getValue() == null ||
@@ -254,6 +297,7 @@ public class AppointmentDialogController {
request.setCustomerId(cbCustomer.getValue().getId());
request.setStoreId(storeId);
request.setServiceId(cbService.getValue().getId());
request.setEmployeeId(cbEmployee.getValue().getId());
request.setAppointmentDate(dpAppointmentDate.getValue());
request.setAppointmentTime(appointmentTime);
request.setAppointmentStatus(cbAppointmentStatus.getValue());

View File

@@ -8,18 +8,22 @@ public class Adoption {
private SimpleIntegerProperty adoptionId;
private SimpleIntegerProperty petId;
private SimpleIntegerProperty customerId;
private SimpleIntegerProperty employeeId;
private SimpleStringProperty petName;
private SimpleStringProperty customerName;
private SimpleStringProperty employeeName;
private SimpleStringProperty adoptionDate;
private SimpleDoubleProperty adoptionFee;
private SimpleStringProperty adoptionStatus;
public Adoption(int adoptionId, int petId, int customerId, String petName, String customerName, String adoptionDate, double adoptionFee, String adoptionStatus) {
public Adoption(int adoptionId, int petId, int customerId, int employeeId, String petName, String customerName, String employeeName, String adoptionDate, double adoptionFee, String adoptionStatus) {
this.adoptionId = new SimpleIntegerProperty(adoptionId);
this.petId = new SimpleIntegerProperty(petId);
this.customerId = new SimpleIntegerProperty(customerId);
this.employeeId = new SimpleIntegerProperty(employeeId);
this.petName = new SimpleStringProperty(petName);
this.customerName = new SimpleStringProperty(customerName);
this.employeeName = new SimpleStringProperty(employeeName);
this.adoptionDate = new SimpleStringProperty(adoptionDate);
this.adoptionFee = new SimpleDoubleProperty(adoptionFee);
this.adoptionStatus = new SimpleStringProperty(adoptionStatus);
@@ -43,6 +47,12 @@ public class Adoption {
public SimpleIntegerProperty customerIdProperty() { return customerId; }
public int getEmployeeId() { return employeeId.get(); }
public void setEmployeeId(int employeeId) { this.employeeId.set(employeeId); }
public SimpleIntegerProperty employeeIdProperty() { return employeeId; }
public String getPetName() { return petName.get(); }
public void setPetName(String petName) { this.petName.set(petName); }
@@ -55,6 +65,12 @@ public class Adoption {
public SimpleStringProperty customerNameProperty() { return customerName; }
public String getEmployeeName() { return employeeName.get(); }
public void setEmployeeName(String employeeName) { this.employeeName.set(employeeName); }
public SimpleStringProperty employeeNameProperty() { return employeeName; }
public String getAdoptionDate() { return adoptionDate.get(); }
public void setAdoptionDate(String adoptionDate) { this.adoptionDate.set(adoptionDate); }

View File

@@ -73,6 +73,7 @@
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0">
@@ -131,6 +132,20 @@
</ComboBox>
</children>
</VBox>
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.rowIndex="2">
<children>
<Label text="Employee:" textFill="#2c3e50">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
<ComboBox fx:id="cbEmployee" prefHeight="29.0" prefWidth="336.0" promptText="Select Employee" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10; -fx-background-color: white;">
<padding>
<Insets bottom="3.0" left="10.0" right="10.0" top="3.0" />
</padding>
</ComboBox>
</children>
</VBox>
</children>
<VBox.margin>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />

View File

@@ -83,6 +83,7 @@
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0">
@@ -190,9 +191,9 @@
</children>
</VBox>
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.rowIndex="2">
<children>
<Label text="Pet:" textFill="#2c3e50">
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.rowIndex="2">
<children>
<Label text="Pet:" textFill="#2c3e50">
<font>
<Font name="System Bold" size="16.0" />
</font>
@@ -201,9 +202,23 @@
<padding>
<Insets bottom="3.0" left="10.0" right="10.0" top="3.0" />
</padding>
</ComboBox>
</children>
</VBox>
</ComboBox>
</children>
</VBox>
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.columnIndex="1" GridPane.rowIndex="3">
<children>
<Label text="Employee:" textFill="#2c3e50">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
<ComboBox fx:id="cbEmployee" prefHeight="29.0" prefWidth="336.0" promptText="Select Employee" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10; -fx-background-color: white;">
<padding>
<Insets bottom="3.0" left="10.0" right="10.0" top="3.0" />
</padding>
</ComboBox>
</children>
</VBox>
</children>
<VBox.margin>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />

View File

@@ -68,11 +68,12 @@
<TableView fx:id="tvAdoptions" prefHeight="362.0" prefWidth="752.0" style="-fx-background-color: white; -fx-background-radius: 12;" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="colAdoptionId" prefWidth="60.0" text="ID" />
<TableColumn fx:id="colPetId" prefWidth="66.2857666015625" text="Pet ID" />
<TableColumn fx:id="colCustomerName" prefWidth="200.57147216796875" text="Customer Name" />
<TableColumn fx:id="colAdoptionDate" prefWidth="190.85711669921875" text="Adoption Date" />
<TableColumn fx:id="colAdoptionFee" prefWidth="91.4285888671875" text="Fee" />
<TableColumn fx:id="colAdoptionStatus" prefWidth="142.28570556640625" text="Status" />
<TableColumn fx:id="colPetId" prefWidth="66.2857666015625" text="Pet ID" />
<TableColumn fx:id="colCustomerName" prefWidth="200.57147216796875" text="Customer Name" />
<TableColumn fx:id="colEmployeeName" prefWidth="160.0" text="Employee" />
<TableColumn fx:id="colAdoptionDate" prefWidth="190.85711669921875" text="Adoption Date" />
<TableColumn fx:id="colAdoptionFee" prefWidth="91.4285888671875" text="Fee" />
<TableColumn fx:id="colAdoptionStatus" prefWidth="120.0" text="Status" />
</columns>
</TableView>
</children>

View File

@@ -68,12 +68,13 @@
<TableView fx:id="tvAppointments" prefHeight="362.0" prefWidth="752.0" style="-fx-background-color: white; -fx-background-radius: 12;" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="colAppointmentId" prefWidth="53.14288330078125" text="ID" />
<TableColumn fx:id="colPetName" prefWidth="108.00003051757812" text="Pet Name" />
<TableColumn fx:id="colServiceName" prefWidth="132.0" text="Service" />
<TableColumn fx:id="colAppointmentDate" prefWidth="101.14288330078125" text="Date" />
<TableColumn fx:id="colAppointmentTime" prefWidth="89.7142333984375" text="Time" />
<TableColumn fx:id="colCustomerName" prefWidth="168.57147216796875" text="Customer" />
<TableColumn fx:id="colAppointmentStatus" prefWidth="98.28570556640625" text="Status" />
<TableColumn fx:id="colPetName" prefWidth="108.00003051757812" text="Pet Name" />
<TableColumn fx:id="colServiceName" prefWidth="132.0" text="Service" />
<TableColumn fx:id="colEmployeeName" prefWidth="132.0" text="Employee" />
<TableColumn fx:id="colAppointmentDate" prefWidth="101.14288330078125" text="Date" />
<TableColumn fx:id="colAppointmentTime" prefWidth="89.7142333984375" text="Time" />
<TableColumn fx:id="colCustomerName" prefWidth="140.0" text="Customer" />
<TableColumn fx:id="colAppointmentStatus" prefWidth="98.28570556640625" text="Status" />
</columns>
</TableView>
</children>