fixed pet busniss logic desktop

This commit is contained in:
Alex
2026-04-13 21:10:35 -06:00
parent 044e9ba7b2
commit 3ef6604884

View File

@@ -31,62 +31,30 @@ import java.util.Optional;
public class PetDialogController { public class PetDialogController {
@FXML private static final String STATUS_AVAILABLE = "Available";
private Button btnCancel; private static final String STATUS_ADOPTED = "Adopted";
private static final String STATUS_OWNED = "Owned";
private static final String STATUS_PENDING = "Pending";
@FXML @FXML private Button btnCancel;
private Button btnSave; @FXML private Button btnSave;
@FXML private Button btnChangeImage;
@FXML @FXML private Button btnRemoveImage;
private Button btnChangeImage; @FXML private ComboBox<String> cbPetStatus;
@FXML private ComboBox<DropdownOption> cbCustomer;
@FXML @FXML private ComboBox<DropdownOption> cbStore;
private Button btnRemoveImage; @FXML private VBox vbCustomerField;
@FXML private VBox vbStoreField;
@FXML @FXML private VBox vbPriceField;
private ComboBox<String> cbPetStatus; @FXML private Label lblMode;
@FXML private Label lblPetId;
@FXML @FXML private Label lblImageStatus;
private ComboBox<DropdownOption> cbCustomer; @FXML private ImageView imgPetPreview;
@FXML private TextField txtPetAge;
@FXML @FXML private TextField txtPetBreed;
private ComboBox<DropdownOption> cbStore; @FXML private TextField txtPetName;
@FXML private TextField txtPetPrice;
@FXML @FXML private ComboBox<String> cbPetSpecies;
private VBox vbCustomerField;
@FXML
private VBox vbStoreField;
@FXML
private VBox vbPriceField;
@FXML
private Label lblMode;
@FXML
private Label lblPetId;
@FXML
private Label lblImageStatus;
@FXML
private ImageView imgPetPreview;
@FXML
private TextField txtPetAge;
@FXML
private TextField txtPetBreed;
@FXML
private TextField txtPetName;
@FXML
private TextField txtPetPrice;
@FXML
private ComboBox<String> cbPetSpecies;
private String mode = null; private String mode = null;
private File selectedImageFile; private File selectedImageFile;
@@ -96,14 +64,14 @@ public class PetDialogController {
private Long pendingCustomerId = null; private Long pendingCustomerId = null;
private Long pendingStoreId = null; private Long pendingStoreId = null;
private Long originalCustomerId = null; private Long originalCustomerId = null;
private boolean isOriginallyOwnedOrAdopted = false;
private ObservableList<String> statusList = FXCollections.observableArrayList( private final ObservableList<String> statusList = FXCollections.observableArrayList(
"Available", "Adopted", "Owned", "Pending" STATUS_AVAILABLE, STATUS_ADOPTED, STATUS_OWNED, STATUS_PENDING
); );
@FXML @FXML
void initialize() { void initialize() {
cbPetStatus.setItems(statusList); cbPetStatus.setItems(statusList);
cbCustomer.setCellFactory(param -> new ListCell<>() { cbCustomer.setCellFactory(param -> new ListCell<>() {
@@ -132,12 +100,14 @@ public class PetDialogController {
} }
}); });
updateStatusFieldVisibility(null); applyStatusRules(STATUS_AVAILABLE, false);
loadSpecies(); loadSpecies();
loadCustomers();
loadStores();
cbPetStatus.valueProperty().addListener((obs, oldVal, newVal) -> { cbPetStatus.valueProperty().addListener((obs, oldVal, newVal) -> {
updateStatusFieldVisibility(newVal); if (newVal != null) applyStatusRules(newVal, true);
}); });
btnSave.setOnMouseClicked(new EventHandler<MouseEvent>() { btnSave.setOnMouseClicked(new EventHandler<MouseEvent>() {
@@ -157,48 +127,57 @@ public class PetDialogController {
btnChangeImage.setOnMouseClicked(mouseEvent -> handleChangeImage()); btnChangeImage.setOnMouseClicked(mouseEvent -> handleChangeImage());
btnRemoveImage.setOnMouseClicked(mouseEvent -> handleRemoveImage()); btnRemoveImage.setOnMouseClicked(mouseEvent -> handleRemoveImage());
refreshImagePreview(); refreshImagePreview();
}
loadCustomers(); private void applyStatusRules(String status, boolean clearInvalidSelections) {
loadStores(); if (STATUS_AVAILABLE.equalsIgnoreCase(status)) {
vbCustomerField.setDisable(true);
vbStoreField.setDisable(false);
if (clearInvalidSelections) cbCustomer.setValue(null);
return;
}
if (STATUS_OWNED.equalsIgnoreCase(status)) {
vbCustomerField.setDisable(false);
vbStoreField.setDisable(true);
if (clearInvalidSelections) cbStore.setValue(null);
return;
}
vbCustomerField.setDisable(false);
vbStoreField.setDisable(false);
} }
private void buttonSaveClicked(MouseEvent mouseEvent) { private void buttonSaveClicked(MouseEvent mouseEvent) {
String errorMsg = ""; String errorMsg = "";
//Check validation (input required)
errorMsg += Validator.isPresent(txtPetName.getText(), "Pet Name"); errorMsg += Validator.isPresent(txtPetName.getText(), "Pet Name");
errorMsg += Validator.isPresent(txtPetAge.getText(), "Age"); errorMsg += Validator.isPresent(txtPetAge.getText(), "Age");
errorMsg += Validator.isPresent(txtPetBreed.getText(), "Breed"); errorMsg += Validator.isPresent(txtPetBreed.getText(), "Breed");
String speciesValue = cbPetSpecies.getValue() != null ? cbPetSpecies.getValue().trim() : ""; String speciesValue = cbPetSpecies.getValue() != null ? cbPetSpecies.getValue().trim() : "";
if (speciesValue.isEmpty()) errorMsg += "Species is required\n"; if (speciesValue.isEmpty()) errorMsg += "Species is required\n";
String selectedStatus = cbPetStatus.getValue(); if (cbPetStatus.getSelectionModel().getSelectedItem() == null) errorMsg += "Status is required\n";
errorMsg += Validator.isPresent(txtPetPrice.getText(), "Price"); errorMsg += Validator.isPresent(txtPetPrice.getText(), "Price");
if (cbPetStatus.getSelectionModel().getSelectedItem() == null){
errorMsg += "Status is required"; String selectedStatus = cbPetStatus.getValue();
if (STATUS_AVAILABLE.equalsIgnoreCase(selectedStatus) && cbStore.getValue() == null) {
errorMsg += "Store is required for Available status\n";
} }
boolean needsCustomer = "Owned".equalsIgnoreCase(selectedStatus) if (STATUS_OWNED.equalsIgnoreCase(selectedStatus) && cbCustomer.getValue() == null) {
|| "Adopted".equalsIgnoreCase(selectedStatus) errorMsg += "Customer is required for Owned status\n";
|| "Pending".equalsIgnoreCase(selectedStatus);
boolean needsStore = requiresStore(selectedStatus);
if (needsCustomer && cbCustomer.getValue() == null && UserSession.getInstance().isAdmin()) {
errorMsg += "Customer is required for " + selectedStatus + " status\n";
} }
if (needsStore && cbStore.getValue() == null) { if (STATUS_ADOPTED.equalsIgnoreCase(selectedStatus)) {
errorMsg += "Store is required for " + selectedStatus + " status\n"; if (cbCustomer.getValue() == null) errorMsg += "Customer is required for Adopted status\n";
if (cbStore.getValue() == null) errorMsg += "Store is required for Adopted status\n";
} }
//Check validation (length size)
errorMsg += Validator.isLessThanVarChars(txtPetName.getText(), "Pet Name", 50); errorMsg += Validator.isLessThanVarChars(txtPetName.getText(), "Pet Name", 50);
errorMsg += Validator.isLessThanVarChars(speciesValue, "Species", 50); errorMsg += Validator.isLessThanVarChars(speciesValue, "Species", 50);
errorMsg += Validator.isLessThanVarChars(txtPetBreed.getText(), "Breed", 50); errorMsg += Validator.isLessThanVarChars(txtPetBreed.getText(), "Breed", 50);
errorMsg += Validator.isLessThanVarChars(txtPetPrice.getText(), "Price", 12); errorMsg += Validator.isLessThanVarChars(txtPetPrice.getText(), "Price", 12);
errorMsg += Validator.isLessThanVarChars(txtPetAge.getText(), "Age", 11); errorMsg += Validator.isLessThanVarChars(txtPetAge.getText(), "Age", 11);
//Check validation (format)
errorMsg += Validator.isNonNegativeDouble(txtPetPrice.getText(), "Price"); errorMsg += Validator.isNonNegativeDouble(txtPetPrice.getText(), "Price");
errorMsg += Validator.isPositiveInteger(txtPetAge.getText(), "Age"); errorMsg += Validator.isPositiveInteger(txtPetAge.getText(), "Age");
if(errorMsg.isEmpty()){ if (errorMsg.isEmpty()) {
if ("Edit".equals(mode) && UserSession.getInstance().isAdmin()) { if ("Edit".equals(mode) && UserSession.getInstance().isAdmin()) {
Long newCustomerId = cbCustomer.getValue() != null ? cbCustomer.getValue().getId() : null; Long newCustomerId = cbCustomer.getValue() != null ? cbCustomer.getValue().getId() : null;
if (!Objects.equals(originalCustomerId, newCustomerId)) { if (!Objects.equals(originalCustomerId, newCustomerId)) {
@@ -206,44 +185,34 @@ public class PetDialogController {
confirm.setHeaderText("Confirm Owner Change"); confirm.setHeaderText("Confirm Owner Change");
confirm.setContentText("Are you sure you want to reassign this pet to a different owner?"); confirm.setContentText("Are you sure you want to reassign this pet to a different owner?");
Optional<ButtonType> result = confirm.showAndWait(); Optional<ButtonType> result = confirm.showAndWait();
if (result.isEmpty() || result.get() != ButtonType.OK) { if (result.isEmpty() || result.get() != ButtonType.OK) return;
return;
}
} }
} }
PetRequest request = buildPetRequest(); PetRequest request = buildPetRequest();
try { try {
if(mode.equals("Add")) { if (mode.equals("Add")) {
PetResponse response = PetApi.getInstance().createPet(request); PetResponse response = PetApi.getInstance().createPet(request);
applyImageChanges(response.getPetId()); applyImageChanges(response.getPetId());
} else { } else {
String[] parts = lblPetId.getText().split(": "); String[] parts = lblPetId.getText().split(": ");
if (parts.length < 2) { if (parts.length < 2) throw new IllegalStateException("Invalid pet ID format");
throw new IllegalStateException("Invalid pet ID format");
}
Long petId = Long.parseLong(parts[1]); Long petId = Long.parseLong(parts[1]);
PetApi.getInstance().updatePet(petId, request); PetApi.getInstance().updatePet(petId, request);
applyImageChanges(petId); applyImageChanges(petId);
} }
//tell the user operation was successful
Alert alert = new Alert(Alert.AlertType.INFORMATION); Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("Saved"); alert.setHeaderText("Saved");
alert.setContentText(mode + " succeeded"); alert.setContentText(mode + " succeeded");
alert.showAndWait(); alert.showAndWait();
closeStage(mouseEvent); closeStage(mouseEvent);
} catch (Exception e) { } catch (Exception e) {
ActivityLogger.getInstance().logException( ActivityLogger.getInstance().logException("PetDialogController.buttonSaveClicked", e, mode + " pet record");
"PetDialogController.buttonSaveClicked",
e,
mode + " pet record");
Alert alert = new Alert(Alert.AlertType.ERROR); Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Operation Error"); alert.setHeaderText("Operation Error");
alert.setContentText(mode + " failed: " + e.getMessage()); alert.setContentText(mode + " failed: " + e.getMessage());
alert.showAndWait(); alert.showAndWait();
} }
} } else {
else{
Alert alert = new Alert(Alert.AlertType.ERROR); Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Input Error"); alert.setHeaderText("Input Error");
alert.setContentText(errorMsg); alert.setContentText(errorMsg);
@@ -257,6 +226,7 @@ public class PetDialogController {
request.setPetSpecies(cbPetSpecies.getValue() != null ? cbPetSpecies.getValue().trim() : ""); request.setPetSpecies(cbPetSpecies.getValue() != null ? cbPetSpecies.getValue().trim() : "");
request.setPetBreed(txtPetBreed.getText()); request.setPetBreed(txtPetBreed.getText());
request.setPetStatus(cbPetStatus.getValue()); request.setPetStatus(cbPetStatus.getValue());
if (txtPetPrice.getText() != null && !txtPetPrice.getText().isBlank()) { if (txtPetPrice.getText() != null && !txtPetPrice.getText().isBlank()) {
try { try {
request.setPetPrice(new BigDecimal(txtPetPrice.getText())); request.setPetPrice(new BigDecimal(txtPetPrice.getText()));
@@ -265,24 +235,14 @@ public class PetDialogController {
} }
} }
int age;
try { try {
age = Integer.parseInt(txtPetAge.getText()); request.setPetAge(Integer.parseInt(txtPetAge.getText()));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid age format"); throw new IllegalArgumentException("Invalid age format");
} }
request.setPetAge(age);
String status = cbPetStatus.getValue(); if (cbCustomer.getValue() != null) request.setCustomerId(cbCustomer.getValue().getId());
boolean customerApplicable = "Owned".equalsIgnoreCase(status) if (cbStore.getValue() != null) request.setStoreId(cbStore.getValue().getId());
|| "Adopted".equalsIgnoreCase(status)
|| "Pending".equalsIgnoreCase(status);
if (customerApplicable && cbCustomer.getValue() != null) {
request.setCustomerId(cbCustomer.getValue().getId());
}
if (requiresStore(status) && cbStore.getValue() != null) {
request.setStoreId(cbStore.getValue().getId());
}
return request; return request;
} }
@@ -297,9 +257,7 @@ public class PetDialogController {
Platform.runLater(() -> { Platform.runLater(() -> {
String current = cbPetSpecies.getValue(); String current = cbPetSpecies.getValue();
cbPetSpecies.setItems(FXCollections.observableArrayList(species)); cbPetSpecies.setItems(FXCollections.observableArrayList(species));
if (current != null && !current.isBlank()) { if (current != null && !current.isBlank()) cbPetSpecies.setValue(current);
cbPetSpecies.setValue(current);
}
}); });
} catch (Exception e) { } catch (Exception e) {
Platform.runLater(() -> ActivityLogger.getInstance().logException( Platform.runLater(() -> ActivityLogger.getInstance().logException(
@@ -318,8 +276,7 @@ public class PetDialogController {
}); });
} catch (Exception e) { } catch (Exception e) {
Platform.runLater(() -> { Platform.runLater(() -> {
ActivityLogger.getInstance().logException( ActivityLogger.getInstance().logException("PetDialogController.loadCustomers", e, "Loading customers");
"PetDialogController.loadCustomers", e, "Loading customers");
cbCustomer.setDisable(true); cbCustomer.setDisable(true);
cbCustomer.setPromptText("Unable to load customers"); cbCustomer.setPromptText("Unable to load customers");
}); });
@@ -337,8 +294,7 @@ public class PetDialogController {
}); });
} catch (Exception e) { } catch (Exception e) {
Platform.runLater(() -> { Platform.runLater(() -> {
ActivityLogger.getInstance().logException( ActivityLogger.getInstance().logException("PetDialogController.loadStores", e, "Loading stores");
"PetDialogController.loadStores", e, "Loading stores");
cbStore.setDisable(true); cbStore.setDisable(true);
cbStore.setPromptText("Unable to load stores"); cbStore.setPromptText("Unable to load stores");
}); });
@@ -378,14 +334,15 @@ public class PetDialogController {
stage.close(); stage.close();
} }
public void displayPetDetails(Pet pet){ public void displayPetDetails(Pet pet) {
if (pet!=null){ if (pet == null) return;
lblPetId.setText("ID: " + pet.getPetId()); lblPetId.setText("ID: " + pet.getPetId());
txtPetName.setText(pet.getPetName()); txtPetName.setText(pet.getPetName());
cbPetSpecies.setValue(pet.getPetSpecies()); cbPetSpecies.setValue(pet.getPetSpecies());
txtPetBreed.setText(pet.getPetBreed()); txtPetBreed.setText(pet.getPetBreed());
txtPetAge.setText(pet.getPetAge() + ""); txtPetAge.setText(String.valueOf(pet.getPetAge()));
txtPetPrice.setText(pet.getPetPrice() + ""); txtPetPrice.setText(String.valueOf(pet.getPetPrice()));
currentImageUrl = pet.getImageUrl(); currentImageUrl = pet.getImageUrl();
selectedImageFile = null; selectedImageFile = null;
removeImageRequested = false; removeImageRequested = false;
@@ -395,46 +352,56 @@ public class PetDialogController {
originalCustomerId = pendingCustomerId; originalCustomerId = pendingCustomerId;
pendingStoreId = pet.getStoreId() > 0 ? pet.getStoreId() : null; pendingStoreId = pet.getStoreId() > 0 ? pet.getStoreId() : null;
isOriginallyOwnedOrAdopted = STATUS_OWNED.equalsIgnoreCase(pet.getPetStatus())
|| STATUS_ADOPTED.equalsIgnoreCase(pet.getPetStatus());
for (String status : cbPetStatus.getItems()) { for (String status : cbPetStatus.getItems()) {
if(status.equals(pet.getPetStatus())){ if (status.equals(pet.getPetStatus())) {
cbPetStatus.getSelectionModel().select(status); cbPetStatus.getSelectionModel().select(status);
break; break;
} }
} }
updateStatusFieldVisibility(cbPetStatus.getValue());
applyStatusLock(); applyStatusRules(cbPetStatus.getValue(), false);
} applyEditModeLock();
} }
private void applyStatusLock() { private void applyEditModeLock() {
String status = cbPetStatus.getValue(); cbPetSpecies.setDisable(true);
boolean isRestricted = "Adopted".equalsIgnoreCase(status) || "Owned".equalsIgnoreCase(status); txtPetBreed.setDisable(true);
boolean isStaff = !UserSession.getInstance().isAdmin(); boolean isStaff = !UserSession.getInstance().isAdmin();
cbPetStatus.setDisable(isRestricted && isStaff); if (isStaff && isOriginallyOwnedOrAdopted) {
cbPetStatus.setDisable(true);
vbCustomerField.setDisable(true);
vbStoreField.setDisable(true);
}
} }
public void setMode(String mode) { public void setMode(String mode) {
this.mode = mode; this.mode = mode;
lblMode.setText(mode + " Pet"); lblMode.setText(mode + " Pet");
if(mode.equals("Add")) {
if (mode.equals("Add")) {
lblPetId.setVisible(false); lblPetId.setVisible(false);
currentImageUrl = null; currentImageUrl = null;
selectedImageFile = null; selectedImageFile = null;
removeImageRequested = false; removeImageRequested = false;
cbPetSpecies.setDisable(false);
txtPetBreed.setDisable(false);
cbPetStatus.setDisable(false);
cbPetStatus.getSelectionModel().select(STATUS_AVAILABLE);
applyStatusRules(STATUS_AVAILABLE, false);
refreshImagePreview(); refreshImagePreview();
} } else if (mode.equals("Edit")) {
else if(mode.equals("Edit")) {
lblPetId.setVisible(true); lblPetId.setVisible(true);
refreshImagePreview(); refreshImagePreview();
} }
updateStatusFieldVisibility(cbPetStatus.getValue());
} }
private void handleChangeImage() { private void handleChangeImage() {
File file = FilePickerSupport.pickImageFile(btnSave.getScene().getWindow()); File file = FilePickerSupport.pickImageFile(btnSave.getScene().getWindow());
if (file == null) { if (file == null) return;
return;
}
selectedImageFile = file; selectedImageFile = file;
removeImageRequested = false; removeImageRequested = false;
lblImageStatus.setText("Selected: " + file.getName()); lblImageStatus.setText("Selected: " + file.getName());
@@ -471,9 +438,7 @@ public class PetDialogController {
} }
private void refreshImagePreview() { private void refreshImagePreview() {
if (imgPetPreview == null || lblImageStatus == null || btnRemoveImage == null) { if (imgPetPreview == null || lblImageStatus == null || btnRemoveImage == null) return;
return;
}
imgPetPreview.setImage(null); imgPetPreview.setImage(null);
if (selectedImageFile != null) { if (selectedImageFile != null) {
lblImageStatus.setText("Selected: " + selectedImageFile.getName()); lblImageStatus.setText("Selected: " + selectedImageFile.getName());
@@ -490,29 +455,4 @@ public class PetDialogController {
lblImageStatus.setText("No image selected"); lblImageStatus.setText("No image selected");
btnRemoveImage.setDisable(true); btnRemoveImage.setDisable(true);
} }
private void updateStatusFieldVisibility(String status) {
if (status == null) {
vbPriceField.setDisable(false);
vbCustomerField.setDisable(true);
vbStoreField.setDisable(false);
return;
}
boolean isAdmin = UserSession.getInstance().isAdmin();
boolean customerApplicable = "Owned".equalsIgnoreCase(status)
|| "Adopted".equalsIgnoreCase(status)
|| "Pending".equalsIgnoreCase(status);
boolean isOwned = "Owned".equalsIgnoreCase(status);
vbPriceField.setDisable(false);
vbCustomerField.setDisable(!customerApplicable || !isAdmin);
vbStoreField.setDisable(isOwned);
}
private boolean requiresStore(String status) {
return "Available".equalsIgnoreCase(status)
|| "Pending".equalsIgnoreCase(status)
|| "Adopted".equalsIgnoreCase(status);
}
} }