Merge pull request '#10 story/pfleger-modul-sperren-und-loschen-von-pflegern' (#37) from story/pfleger-modul-sperren-und-loschen-von-pflegern into main
All checks were successful
Quality Check / Linting Check (push) Successful in 19s
Javadoc Deploy / Javadoc (push) Successful in 34s
Quality Check / Javadoc Check (push) Successful in 31s

Reviewed-on: #37
Reviewed-by: Dominik Säume <dominik.saeume@hmmh.de>
This commit is contained in:
SZUT-Dorian 2024-05-16 11:57:12 +00:00
commit 6908e8129b
11 changed files with 420 additions and 25 deletions

Binary file not shown.

View file

@ -46,6 +46,14 @@ public class NurseFixture implements Fixture<Nurse> {
"Armout", "Armout",
"9876543210" "9876543210"
)); ));
nurses.add(new Nurse(
"Björnd",
"Heideberger",
"69420",
true
));
NurseDao dao = DaoFactory.getInstance().createNurseDAO(); NurseDao dao = DaoFactory.getInstance().createNurseDAO();
for (Nurse nurse : nurses) { for (Nurse nurse : nurses) {
dao.create(nurse); dao.create(nurse);

View file

@ -1,8 +1,10 @@
package de.hitec.nhplus.main; package de.hitec.nhplus.main;
import de.hitec.nhplus.Main; import de.hitec.nhplus.Main;
import de.hitec.nhplus.nurse.Nurse;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.control.SelectionModel;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TabPane; import javafx.scene.control.TabPane;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
@ -16,6 +18,8 @@ import java.util.Objects;
* *
* @author Bernd Heidemann * @author Bernd Heidemann
* @author Dominik Säume * @author Dominik Säume
* @author Armin Ribic
* @author Dorian Nemec
*/ */
public class MainWindowController { public class MainWindowController {
@FXML @FXML
@ -29,14 +33,25 @@ public class MainWindowController {
@FXML @FXML
private Tab treatmentTab; private Tab treatmentTab;
@FXML @FXML
private AnchorPane nursePage;
@FXML
private Tab nurseTab; private Tab nurseTab;
@FXML @FXML
private TabPane nurseTabPane;
@FXML
private AnchorPane activeNursePage;
@FXML
private Tab activeNurseTab;
@FXML
private AnchorPane lockedNursePage;
@FXML
private Tab lockedNurseTab;
@FXML
private AnchorPane medicationPage; private AnchorPane medicationPage;
@FXML @FXML
private Tab medicationTab; private Tab medicationTab;
/**
* Initialization method that is called after the binding of all the fields.
*/
@FXML @FXML
public void initialize() { public void initialize() {
loadPatientPage(); loadPatientPage();
@ -46,6 +61,12 @@ public class MainWindowController {
treatmentTab.setOnSelectionChanged(event -> loadTreatmentsPage()); treatmentTab.setOnSelectionChanged(event -> loadTreatmentsPage());
nurseTab.setOnSelectionChanged(event -> loadNursePage()); nurseTab.setOnSelectionChanged(event -> loadNursePage());
medicationTab.setOnSelectionChanged(event -> loadMedicationPage()); medicationTab.setOnSelectionChanged(event -> loadMedicationPage());
nurseTabPane.getSelectionModel().select(activeNurseTab);
activeNurseTab.setOnSelectionChanged(event -> loadActiveNursePage());
lockedNurseTab.setOnSelectionChanged(event -> loadLockedNursePage());
} }
/** /**
@ -67,7 +88,7 @@ public class MainWindowController {
} }
/** /**
* Loads the treatment page into its tab. * Loads the {@link } page into its tab.
*/ */
private void loadTreatmentsPage() { private void loadTreatmentsPage() {
try { try {
@ -88,15 +109,47 @@ public class MainWindowController {
* Loads the nurse page into its tab. * Loads the nurse page into its tab.
*/ */
private void loadNursePage() { private void loadNursePage() {
SelectionModel<Tab> selectionModel = nurseTabPane.getSelectionModel();
Tab selectedTab = selectionModel.getSelectedItem();
if(selectedTab == activeNurseTab){
loadActiveNursePage();
}
if(selectedTab == lockedNurseTab){
loadLockedNursePage();
}
}
/**
* Loads the active {@link Nurse} page into its tab.
*/
private void loadActiveNursePage() {
try { try {
BorderPane nursePane = FXMLLoader.load( BorderPane activeNursePane = FXMLLoader.load(
Objects.requireNonNull(Main.class.getResource("/de/hitec/nhplus/nurse/AllNurseView.fxml")) Objects.requireNonNull(Main.class.getResource("/de/hitec/nhplus/nurse/AllNurseView.fxml"))
); );
nursePage.getChildren().setAll(nursePane); activeNursePage.getChildren().setAll(activeNursePane);
AnchorPane.setTopAnchor(nursePane, 0d); AnchorPane.setTopAnchor(activeNursePane, 0d);
AnchorPane.setBottomAnchor(nursePane, 0d); AnchorPane.setBottomAnchor(activeNursePane, 0d);
AnchorPane.setLeftAnchor(nursePane, 0d); AnchorPane.setLeftAnchor(activeNursePane, 0d);
AnchorPane.setRightAnchor(nursePane, 0d); AnchorPane.setRightAnchor(activeNursePane, 0d);
} catch (IOException exception) {
exception.printStackTrace();
}
}
/**
* Loads the locked {@link Nurse} page into its tab.
*/
private void loadLockedNursePage() {
try {
BorderPane lockedNursePane = FXMLLoader.load(
Objects.requireNonNull(Main.class.getResource("/de/hitec/nhplus/nurse/LockedNurseView.fxml"))
);
lockedNursePage.getChildren().setAll(lockedNursePane);
AnchorPane.setTopAnchor(lockedNursePane, 0d);
AnchorPane.setBottomAnchor(lockedNursePane, 0d);
AnchorPane.setLeftAnchor(lockedNursePane, 0d);
AnchorPane.setRightAnchor(lockedNursePane, 0d);
} catch (IOException exception) { } catch (IOException exception) {
exception.printStackTrace(); exception.printStackTrace();
} }

View file

@ -33,6 +33,8 @@ public class AllNurseController {
@FXML @FXML
public Button buttonAdd; public Button buttonAdd;
@FXML @FXML
public Button buttonLock;
@FXML
private TableView<Nurse> tableView; private TableView<Nurse> tableView;
@FXML @FXML
private TableColumn<Nurse, Long> columnId; private TableColumn<Nurse, Long> columnId;
@ -89,7 +91,7 @@ public class AllNurseController {
this.nurses.clear(); this.nurses.clear();
this.dao = DaoFactory.getInstance().createNurseDAO(); this.dao = DaoFactory.getInstance().createNurseDAO();
try { try {
this.nurses.setAll(this.dao.readAll()); this.nurses.setAll(this.dao.readAllActive());
}catch (SQLException exception){ }catch (SQLException exception){
exception.printStackTrace(); exception.printStackTrace();
} }
@ -119,5 +121,20 @@ public class AllNurseController {
clearTextfields(); clearTextfields();
} }
@FXML
public void handleLock(){
Nurse selectedItem = this.tableView.getSelectionModel().getSelectedItem();
if (selectedItem == null){
return;
}
try {
selectedItem.setLocked(true);
this.dao.update(selectedItem);
}catch (SQLException exception){
exception.printStackTrace();
}
readAllAndShowInTableView();
}
} }

View file

@ -0,0 +1,136 @@
package de.hitec.nhplus.nurse;
import de.hitec.nhplus.datastorage.DaoFactory;
import de.hitec.nhplus.nurse.database.NurseDao;
import de.hitec.nhplus.treatment.Treatment;
import de.hitec.nhplus.treatment.database.TreatmentDao;
import de.hitec.nhplus.utils.DateConverter;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Controller for all locked nurses.
* @author Armin Ribic
* @author Dorian Nemec
*/
public class LockedNurseController {
@FXML
public Button buttonDelete;
@FXML
private Button buttonUnlock;
@FXML
public TableView<Nurse> tableView;
@FXML
public TableColumn<Nurse, Long> columnId;
@FXML
public TableColumn<Nurse, String> columnFirstName;
@FXML
public TableColumn<Nurse, String> columnSurName;
@FXML
public TableColumn<Nurse, String> columnPhoneNumber;
@FXML
public TableColumn<Nurse, String> columnDeleteDate;
private final ObservableList<Nurse> nurses = FXCollections.observableArrayList();
private final Map<Nurse, List<Treatment>> treatmentsPerNurse = new HashMap<>();
private NurseDao dao;
private TreatmentDao treatmentDao;
/**
* This method allows initializing a {@link LockedNurseController} object
* that is called after the binding of all the fields.
*/
public void initialize() {
this.readAllAndShowInTableView();
this.columnId.setCellValueFactory(new PropertyValueFactory<>("id"));
this.columnFirstName.setCellValueFactory(new PropertyValueFactory<>("firstName"));
this.columnSurName.setCellValueFactory(new PropertyValueFactory<>("surName"));
this.columnPhoneNumber.setCellValueFactory(new PropertyValueFactory<>("phoneNumber"));
this.columnDeleteDate.setCellValueFactory(cellData -> new SimpleStringProperty(
DateConverter.convertLocalDateToString(cellData.getValue().calculateDeleteDate()))
);
buttonDelete.setDisable(true);
this.tableView.setItems(this.nurses);
}
/**
* Reads all locked {@link Nurse} data and shows it in the table.
*/
private void readAllAndShowInTableView() {
this.nurses.clear();
this.treatmentsPerNurse.clear();
this.dao = DaoFactory.getInstance().createNurseDAO();
this.treatmentDao = DaoFactory.getInstance().createTreatmentDao();
try {
this.nurses.addAll(this.dao.readAllLocked());
this.nurses.forEach(
nurse -> {
try {
this.treatmentsPerNurse.put(nurse, this.treatmentDao.readTreatmentsByNurse(nurse.getId()));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
);
} catch (SQLException exception) {
exception.printStackTrace();
}
}
@FXML
public void handleDelete() {
Nurse selectedItem = this.tableView.getSelectionModel().getSelectedItem();
if (selectedItem == null) {
return;
}
try {
this.dao.delete(selectedItem.getId());
} catch (SQLException exception) {
exception.printStackTrace();
}
readAllAndShowInTableView();
}
@FXML
public void handleMouseClick() {
Nurse nurse = tableView.getSelectionModel().getSelectedItem();
boolean canBeDeleted = nurse.calculateDeleteDate().isBefore(LocalDate.now());
buttonDelete.setDisable(!canBeDeleted);
}
@FXML
public void unlockNurse() {
Nurse selectedItem = this.tableView.getSelectionModel().getSelectedItem();
if (selectedItem == null) {
return;
}
try {
selectedItem.setLocked(false);
this.dao.update(selectedItem);
} catch (SQLException exception) {
exception.printStackTrace();
}
readAllAndShowInTableView();
}
}

View file

@ -1,26 +1,36 @@
package de.hitec.nhplus.nurse; package de.hitec.nhplus.nurse;
import de.hitec.nhplus.datastorage.DaoFactory;
import de.hitec.nhplus.main.Person; import de.hitec.nhplus.main.Person;
import de.hitec.nhplus.treatment.Treatment;
import de.hitec.nhplus.utils.DateConverter;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.SimpleStringProperty;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.StringJoiner; import java.util.StringJoiner;
/** /**
* The model for a {@link Nurse}. * The model for a {@link Nurse}.
* *
* @author Dominik Säume * @author Dominik Säume
* @author Armin Ribic
* @author Dorian Nemec
*/ */
public class Nurse extends Person { public class Nurse extends Person {
private SimpleIntegerProperty id; private SimpleIntegerProperty id;
private final SimpleStringProperty phoneNumber; private final SimpleStringProperty phoneNumber;
private final SimpleBooleanProperty locked;
/** /**
* This constructor allows instantiating a {@link Nurse} object, * This constructor allows instantiating a {@link Nurse} object,
* before it is stored in the database, by omitting the {@link Nurse#id ID} value. * before it is stored in the database, by omitting the {@link Nurse#id ID} value.
* * It includes the locked Property.
* @implSpec Instances created with this constructor can be directly passed to * @implSpec This was added for usage in the {@link de.hitec.nhplus.fixtures.NurseFixture NurseFixture}.
* {@link de.hitec.nhplus.nurse.database.NurseDao#create NurseDao.create}.
*/ */
public Nurse( public Nurse(
String firstName, String firstName,
@ -29,6 +39,22 @@ public class Nurse extends Person {
) { ) {
super(firstName, surName); super(firstName, surName);
this.phoneNumber = new SimpleStringProperty(phoneNumber); this.phoneNumber = new SimpleStringProperty(phoneNumber);
this.locked = new SimpleBooleanProperty(false);
}
/**
* This constructor allows instantiating a {@link Nurse} object with
* specifying if the nurse is locked or not.
*/
public Nurse(
String firstName,
String surName,
String phoneNumber,
Boolean isLocked
) {
super(firstName, surName);
this.phoneNumber = new SimpleStringProperty(phoneNumber);
this.locked = new SimpleBooleanProperty(isLocked);
} }
/** /**
@ -38,11 +64,38 @@ public class Nurse extends Person {
int id, int id,
String firstName, String firstName,
String surName, String surName,
String phoneNumber String phoneNumber,
Boolean isLocked
) { ) {
super(firstName, surName); super(firstName, surName);
this.id = new SimpleIntegerProperty(id); this.id = new SimpleIntegerProperty(id);
this.phoneNumber = new SimpleStringProperty(phoneNumber); this.phoneNumber = new SimpleStringProperty(phoneNumber);
this.locked = new SimpleBooleanProperty(isLocked);
}
/**
* Calculates the date when the {@link Nurse} can be deleted.
*/
public LocalDate calculateDeleteDate() {
List<Treatment> treatments;
try {
treatments = DaoFactory.getInstance().createTreatmentDao().readTreatmentsByNurse(this.getId());
}catch (SQLException exception){
treatments = null;
}
if(treatments == null){
return LocalDate.now().plusDays(1);
}
LocalDate newestDate = LocalDate.of(1980, 1, 1);
for (Treatment treatment : treatments) {
LocalDate date = DateConverter.convertStringToLocalDate(treatment.getDate());
if (date.isAfter(newestDate)) {
newestDate = date;
}
}
return newestDate.plusYears(10);
} }
public void setPhoneNumber(String phoneNumber) { public void setPhoneNumber(String phoneNumber) {
@ -65,6 +118,19 @@ public class Nurse extends Person {
return phoneNumber; return phoneNumber;
} }
public boolean isLocked() {
return locked.get();
}
public SimpleBooleanProperty lockedProperty() {
return locked;
}
public void setLocked(boolean locked) {
this.locked.set(locked);
}
@Override @Override
public String toString() { public String toString() {
return new StringJoiner(System.lineSeparator()) return new StringJoiner(System.lineSeparator())
@ -73,6 +139,7 @@ public class Nurse extends Person {
.add("FirstName: " + this.getFirstName()) .add("FirstName: " + this.getFirstName())
.add("SurName: " + this.getSurName()) .add("SurName: " + this.getSurName())
.add("PhoneNumber: " + this.getPhoneNumber()) .add("PhoneNumber: " + this.getPhoneNumber())
.add("IsLocked: " + this.isLocked())
.toString(); .toString();
} }

View file

@ -17,6 +17,7 @@ import java.util.List;
* @author Dominik Säume * @author Dominik Säume
*/ */
public class NurseDao extends DaoImp<Nurse> { public class NurseDao extends DaoImp<Nurse> {
public NurseDao(Connection connection) { public NurseDao(Connection connection) {
super(connection); super(connection);
} }
@ -25,13 +26,14 @@ public class NurseDao extends DaoImp<Nurse> {
protected PreparedStatement getCreateStatement(Nurse nurse) throws SQLException { protected PreparedStatement getCreateStatement(Nurse nurse) throws SQLException {
final String SQL = """ final String SQL = """
INSERT INTO nurse INSERT INTO nurse
(firstName, surName, phoneNumber) (firstName, surName, phoneNumber, isLocked)
VALUES (?, ?, ?) VALUES (?, ?, ?, ?)
"""; """;
PreparedStatement statement = this.connection.prepareStatement(SQL); PreparedStatement statement = this.connection.prepareStatement(SQL);
statement.setString(1, nurse.getFirstName()); statement.setString(1, nurse.getFirstName());
statement.setString(2, nurse.getSurName()); statement.setString(2, nurse.getSurName());
statement.setString(3, nurse.getPhoneNumber()); statement.setString(3, nurse.getPhoneNumber());
statement.setBoolean(4, nurse.isLocked());
return statement; return statement;
} }
@ -49,7 +51,8 @@ public class NurseDao extends DaoImp<Nurse> {
result.getInt(1), result.getInt(1),
result.getString(2), result.getString(2),
result.getString(3), result.getString(3),
result.getString(4) result.getString(4),
result.getBoolean(5)
); );
} }
@ -58,7 +61,6 @@ public class NurseDao extends DaoImp<Nurse> {
final String SQL = "SELECT * FROM nurse"; final String SQL = "SELECT * FROM nurse";
return this.connection.prepareStatement(SQL); return this.connection.prepareStatement(SQL);
} }
@Override @Override
protected List<Nurse> getListFromResultSet(ResultSet result) throws SQLException { protected List<Nurse> getListFromResultSet(ResultSet result) throws SQLException {
ArrayList<Nurse> list = new ArrayList<>(); ArrayList<Nurse> list = new ArrayList<>();
@ -68,20 +70,38 @@ public class NurseDao extends DaoImp<Nurse> {
return list; return list;
} }
/**
* Read all database entries of active {@link Nurse}s into a {@link List} of model instances.
*/
public List<Nurse> readAllActive() throws SQLException {
final String SQL = "SELECT * FROM nurse WHERE isLocked=false";
return getListFromResultSet(this.connection.prepareStatement(SQL).executeQuery());
}
/**
* Read all database entries of locked {@link Nurse}s into a {@link List} of model instances.
*/
public List<Nurse> readAllLocked() throws SQLException {
final String SQL = "SELECT * FROM nurse WHERE isLocked=true";
return getListFromResultSet(this.connection.prepareStatement(SQL).executeQuery());
}
@Override @Override
protected PreparedStatement getUpdateStatement(Nurse nurse) throws SQLException { protected PreparedStatement getUpdateStatement(Nurse nurse) throws SQLException {
final String SQL = """ final String SQL = """
UPDATE nurse SET UPDATE nurse SET
firstName = ?, firstName = ?,
surName = ?, surName = ?,
phoneNumber = ? phoneNumber = ?,
isLocked = ?
WHERE id = ? WHERE id = ?
"""; """;
PreparedStatement statement = this.connection.prepareStatement(SQL); PreparedStatement statement = this.connection.prepareStatement(SQL);
statement.setString(1, nurse.getFirstName()); statement.setString(1, nurse.getFirstName());
statement.setString(2, nurse.getSurName()); statement.setString(2, nurse.getSurName());
statement.setString(3, nurse.getPhoneNumber()); statement.setString(3, nurse.getPhoneNumber());
statement.setInt(4, nurse.getId()); statement.setBoolean(4, nurse.isLocked());
statement.setInt(5, nurse.getId());
return statement; return statement;
} }
@ -92,4 +112,6 @@ public class NurseDao extends DaoImp<Nurse> {
statement.setInt(1, id); statement.setInt(1, id);
return statement; return statement;
} }
} }

View file

@ -16,7 +16,14 @@
<AnchorPane fx:id="treatmentPage"/> <AnchorPane fx:id="treatmentPage"/>
</Tab> </Tab>
<Tab fx:id="nurseTab" text="Pfleger"> <Tab fx:id="nurseTab" text="Pfleger">
<AnchorPane fx:id="nursePage"/> <TabPane fx:id="nurseTabPane" tabClosingPolicy="UNAVAILABLE">
<Tab fx:id="activeNurseTab" text="Pfleger">
<AnchorPane fx:id="activeNursePage"/>
</Tab>
<Tab fx:id="lockedNurseTab" text="Gesperrte Pfleger">
<AnchorPane fx:id="lockedNursePage"/>
</Tab>
</TabPane>
</Tab> </Tab>
<Tab fx:id="medicationTab" text="Medikamente"> <Tab fx:id="medicationTab" text="Medikamente">
<AnchorPane fx:id="medicationPage"/> <AnchorPane fx:id="medicationPage"/>

View file

@ -77,10 +77,11 @@
text="Hinzufügen" text="Hinzufügen"
/> />
<Button <Button
fx:id="buttonDelete" fx:id="buttonLock"
mnemonicParsing="false" mnemonicParsing="false"
onAction="#handleLock"
prefWidth="90.0" prefWidth="90.0"
text="Löschen" text="Sperren"
/> />
</HBox> </HBox>
</right> </right>

View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="de.hitec.nhplus.nurse.LockedNurseController"
>
<padding>
<Insets top="8" left="8" right="8" bottom="8"/>
</padding>
<center>
<TableView fx:id="tableView" layoutX="31.0" layoutY="40" onMouseClicked="#handleMouseClick" >
<columns>
<TableColumn
fx:id="columnId"
minWidth="40.0"
text="ID"
/>
<TableColumn
fx:id="columnSurName"
minWidth="140.0"
text="Nachname"
/>
<TableColumn
fx:id="columnFirstName"
minWidth="140.0"
text="Vorname"
/>
<TableColumn
fx:id="columnPhoneNumber"
minWidth="140.0"
text="Telefonnummer"
/>
<TableColumn
fx:id="columnDeleteDate"
minWidth="140.0"
text="Löschen ab"
/>
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
</columnResizePolicy>
</TableView>
</center>
<bottom>
<BorderPane>
<BorderPane.margin>
<Insets top="8.0"/>
</BorderPane.margin>
<center>
<HBox spacing="8.0">
<padding>
<Insets right="8.0"/>
</padding>
</HBox>
</center>
<right>
<HBox>
<spacing>8.0</spacing>
<Button
fx:id="buttonUnlock"
mnemonicParsing="false"
onAction="#unlockNurse"
prefWidth="90.0"
text="Entsperren"
/>
<Button
fx:id="buttonDelete"
mnemonicParsing="false"
onAction="#handleDelete"
prefWidth="90.0"
text="Löschen"
/>
</HBox>
</right>
</BorderPane>
</bottom>
</BorderPane>

View file

@ -3,5 +3,6 @@ CREATE TABLE nurse
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
firstName TEXT NOT NULL, firstName TEXT NOT NULL,
surName TEXT NOT NULL, surName TEXT NOT NULL,
phoneNumber TEXT NOT NULL phoneNumber TEXT NOT NULL,
isLocked BOOLEAN NOT NULL DEFAULT false
) )