Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OP-1197 | Validate ward Inventory #1456

Merged
merged 26 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a6eafc3
Add new column on medicalinventory
JantBogard Nov 19, 2024
c9e61e9
add validate ward inventory row function
JantBogard Nov 20, 2024
fda7889
Merge commit '9de0c494352aad72afe1a381ed5a1e41fdd99a14' into OP-1193_…
JantBogard Nov 20, 2024
95768bb
Merge branch 'develop' into OP-1193_OP-1194_OP-1197
JantBogard Nov 20, 2024
e9441a5
Remove uneccessary format code
JantBogard Nov 20, 2024
eaa06f4
Remove uneccessary format code
JantBogard Nov 20, 2024
2fe89dd
Write united test for validateWardinventory
JantBogard Nov 22, 2024
65e2238
Merge branch 'develop' into OP-1193_OP-1194_OP-1197
JantBogard Nov 22, 2024
efb091e
Add the standard license header block
JantBogard Nov 25, 2024
cb7d385
Merge branch 'develop' into OP-1193_OP-1194_OP-1197
JantBogard Nov 27, 2024
6b9925f
Remove reason attribut
JantBogard Nov 27, 2024
6d2e1e9
Add actualize inventory row function
JantBogard Nov 28, 2024
23c35f5
Merge branch 'develop' into OP-1193_OP-1194_OP-1197
JantBogard Nov 29, 2024
10c2d3d
update validateMedicalWardInventoryRow function
JantBogard Dec 3, 2024
7a71250
Merge branch 'develop' into OP-1193_OP-1194_OP-1197
JantBogard Dec 3, 2024
5892e90
update validateMedicalWardInventoryRow function
JantBogard Dec 3, 2024
f01faa7
Update src/main/java/org/isf/medicalinventory/manager/MedicalInventor…
JantBogard Dec 9, 2024
5415bf9
Update src/main/java/org/isf/medicalinventory/manager/MedicalInventor…
JantBogard Dec 9, 2024
1d9750e
Update src/main/java/org/isf/medicalinventory/manager/MedicalInventor…
JantBogard Dec 9, 2024
51f2974
Applying suggestion for change
JantBogard Dec 9, 2024
07881cd
Fix test coverage
JantBogard Dec 10, 2024
24489e4
Update test validation medical ward inventory row
JantBogard Dec 12, 2024
66a1579
Update test validation medical ward inventory row
JantBogard Dec 12, 2024
6569133
Merge branch 'develop' into OP-1193_OP-1194_OP-1197
JantBogard Dec 12, 2024
a3084ae
Add actualize inventory row test
JantBogard Dec 18, 2024
cc00c27
Merge branch 'develop' into OP-1193_OP-1194_OP-1197
mwithi Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
JantBogard marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE OH_MEDICALDSRINVENTORY ADD COLUMN MINVT_DESC VARCHAR(100) NULL;
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
import org.isf.medstockmovtype.model.MovementType;
import org.isf.supplier.manager.SupplierBrowserManager;
import org.isf.supplier.model.Supplier;
import org.isf.medicalstockward.manager.MovWardBrowserManager;
import org.isf.medicalstockward.model.MedicalWard;
import org.isf.medicalstockward.model.MovementWard;
import org.isf.utils.exception.OHDataValidationException;
import org.isf.utils.exception.OHServiceException;
import org.isf.utils.exception.model.OHExceptionMessage;
Expand Down Expand Up @@ -72,17 +75,20 @@ public class MedicalInventoryManager {

private WardBrowserManager wardManager;

private MovWardBrowserManager movWardBrowserManager;

public MedicalInventoryManager(MedicalInventoryIoOperation medicalInventoryIoOperation, MedicalInventoryRowManager medicalInventoryRowManager,
MedicalDsrStockMovementTypeBrowserManager medicalDsrStockMovementTypeBrowserManager,
SupplierBrowserManager supplierManager, MovStockInsertingManager movStockInsertingManager, WardBrowserManager wardManager,
MovBrowserManager movBrowserManager) {
MedicalDsrStockMovementTypeBrowserManager medicalDsrStockMovementTypeBrowserManager,
SupplierBrowserManager supplierManager, MovStockInsertingManager movStockInsertingManager, WardBrowserManager wardManager,
MovBrowserManager movBrowserManager, MovWardBrowserManager movWardBrowserManager) {
this.ioOperations = medicalInventoryIoOperation;
this.medicalInventoryRowManager = medicalInventoryRowManager;
this.medicalDsrStockMovementTypeBrowserManager = medicalDsrStockMovementTypeBrowserManager;
this.supplierManager = supplierManager;
this.movStockInsertingManager = movStockInsertingManager;
this.wardManager = wardManager;
this.movBrowserManager = movBrowserManager;
this.movWardBrowserManager = movWardBrowserManager;
}

/**
Expand Down Expand Up @@ -293,7 +299,7 @@ public void validateMedicalInventoryRow(MedicalInventory inventory, List<Medical
Optional<Lot> optLot = movStockInsertingManager.getLotByMedical(medical, false).stream().filter(l -> l.getCode().equals(lotCodeOfMovement))
.findFirst();
if (optLot.isPresent()) {
mainStoreQty = optLot.get().getMainStoreQuantity();
mainStoreQty = optLot.get().getMainStoreQuantity();
}

// Search for the specific Lot and Medical in inventoryRowSearchList (Lot should be enough)
Expand Down Expand Up @@ -355,6 +361,105 @@ public void validateMedicalInventoryRow(MedicalInventory inventory, List<Medical
}
}

/**
* Validate the Inventory rows of inventory ward.
*
* @param inventory - The {@link MedicalInventory}
* @param inventoryRowSearchList - The list of {@link MedicalInventory}
* @throws OHServiceException
*/
public void validateMedicalWardInventoryRow(MedicalInventory inventory, List<MedicalInventoryRow> inventoryRowSearchList) throws OHServiceException {
LocalDateTime movFrom = inventory.getLastModifiedDate();
JantBogard marked this conversation as resolved.
Show resolved Hide resolved
LocalDateTime movTo = TimeTools.getNow();
StringBuilder medDescriptionForLotUpdated = new StringBuilder("\n"); // initial new line
StringBuilder medDescriptionForNewLot = new StringBuilder("\n"); // initial new line
StringBuilder medDescriptionForNewMedical = new StringBuilder("\n"); // initial new line
boolean lotUpdated = false;
boolean lotAdded = false;
boolean medicalAdded = false;

List<MovementWard> movementWards = new ArrayList<>(movWardBrowserManager.getMovementWard(inventory.getWard(), movFrom, movTo));
List<Movement> movementToWards = new ArrayList<>(movBrowserManager.getMovements(inventory.getWard(), movFrom, movTo));
List<Medical> inventoryMedicalsList = inventoryRowSearchList.stream().map(MedicalInventoryRow::getMedical).distinct().toList();

// Get all the lot of the ward movements
List<Lot> lotOfMovements = new ArrayList<>(movementWards.stream().map(MovementWard::getLot).toList());
JantBogard marked this conversation as resolved.
Show resolved Hide resolved
// Get all the lot of the movements
lotOfMovements.addAll(movementToWards.stream().map(Movement::getLot).toList());
JantBogard marked this conversation as resolved.
Show resolved Hide resolved
// Remove duplicates by converting the list to a set
Set<Lot> uniqueLots = new HashSet<>(lotOfMovements);
// Convert the set back to a list
List<Lot> uniqueLotList = new ArrayList<>(uniqueLots);
// Cycle fetched movements to see if they impact inventoryRowSearchList
for (Lot lot : uniqueLotList) {
String lotCodeOfMovement = lot.getCode();
JantBogard marked this conversation as resolved.
Show resolved Hide resolved
String lotExpiringDate = TimeTools.formatDateTime(lot.getDueDate(), TimeTools.DD_MM_YYYY);
String lotInfo = GeneralData.AUTOMATICLOT_IN ? lotExpiringDate : lotCodeOfMovement;
Medical medical = lot.getMedical();
String medicalDesc = medical.getDescription();
Integer medicalCode = medical.getCode();
double wardStoreQty = 0.0;

Optional<MedicalWard> optMedicalWard = movWardBrowserManager.getMedicalsWard(inventory.getWard(), medical.getCode(), false).stream()
.filter(m -> m.getLot().getCode().equals(lotCodeOfMovement)).findFirst();

if (optMedicalWard.isPresent()) {
wardStoreQty = optMedicalWard.get().getQty();
}
JantBogard marked this conversation as resolved.
Show resolved Hide resolved

// Search for the specific Lot and Medical in inventoryRowSearchList (Lot should be enough)
Optional<MedicalInventoryRow> matchingRow = inventoryRowSearchList.stream()
.filter(row -> row.getLot().getCode().equals(lotCodeOfMovement) && row.getMedical().getCode().equals(medicalCode)).findFirst();
JantBogard marked this conversation as resolved.
Show resolved Hide resolved

if (matchingRow.isPresent()) {
MedicalInventoryRow medicalInventoryRow = matchingRow.get();
double theoQty = medicalInventoryRow.getTheoreticQty();
if (wardStoreQty != theoQty) {
lotUpdated = true;
medDescriptionForLotUpdated
.append("\n")
.append(MessageBundle.formatMessage("angal.inventory.theoreticalqtyhavebeenupdatedforsomemedical.detail.fmt.msg",
medicalDesc, lotInfo, theoQty, wardStoreQty, wardStoreQty - theoQty));
}
} else {
// TODO: to decide if to give control to the user about this
if (!inventoryMedicalsList.contains(medical)) {
// New medical
medicalAdded = true;
medDescriptionForNewMedical
.append("\n")
.append(MessageBundle.formatMessage("angal.inventory.newmedicalshavebeenfound.detail.fmt.msg",
medicalDesc, lotInfo, wardStoreQty));
} else {
// New Lot
lotAdded = true;
medDescriptionForNewLot
.append("\n")
.append(MessageBundle.formatMessage("angal.inventory.newlotshavebeenaddedforsomemedical.detail.fmt.msg",
medicalDesc, lotInfo, wardStoreQty));
}
}
}
List<OHExceptionMessage> errors = new ArrayList<>();
JantBogard marked this conversation as resolved.
Show resolved Hide resolved
if (lotUpdated) {
errors.add(new OHExceptionMessage(MessageBundle.getMessage("angal.inventory.validate.btn"),
JantBogard marked this conversation as resolved.
Show resolved Hide resolved
MessageBundle.formatMessage("angal.inventory.theoreticalqtyhavebeenupdatedforsomemedicalward.fmt.msg", medDescriptionForLotUpdated),
OHSeverityLevel.INFO));
}
if (lotAdded) {
errors.add(new OHExceptionMessage(MessageBundle.getMessage("angal.inventory.validate.btn"),
MessageBundle.formatMessage("angal.inventory.newlotshavebeenaddedforsomemedicalward.fmt.msg", medDescriptionForNewLot),
OHSeverityLevel.INFO));
}
if (medicalAdded) {
errors.add(new OHExceptionMessage(MessageBundle.getMessage("angal.inventory.validate.btn"),
MessageBundle.formatMessage("angal.inventory.newmedicalshavebeenfoundward.fmt.msg", medDescriptionForNewMedical), OHSeverityLevel.INFO));
}
if (!errors.isEmpty()) {
throw new OHDataValidationException(errors);
}
}

/**
* Marks an inventory as deleted by changing its status.
*
Expand Down Expand Up @@ -388,7 +493,7 @@ public void deleteInventory(MedicalInventory medicalInventory) throws OHServiceE
public List<Movement> confirmMedicalInventoryRow(MedicalInventory inventory, List<MedicalInventoryRow> inventoryRowSearchList) throws OHServiceException {
// validate the inventory
this.validateMedicalInventoryRow(inventory, inventoryRowSearchList);

// get general info
String referenceNumber = inventory.getInventoryReference();
// TODO: to explore the possibility to allow charges and discharges with same referenceNumber
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/org/isf/medicalinventory/model/MedicalInventory.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ public class MedicalInventory extends Auditable<String> {

@Column(name = "MINVT_DESTINATION")
private String destination;

@Column(name = "MINVT_DESC")
private String reason;

@Version
@Column(name="MINVT_LOCK")
Expand Down Expand Up @@ -120,6 +123,19 @@ public MedicalInventory(Integer id, String status, LocalDateTime inventoryDate,
this.destination = destination;
}

public MedicalInventory(Integer id, String status, LocalDateTime inventoryDate, String user, String inventoryReference, String inventoryType, String ward,
String destination, String reason) {
this.id = id;
this.status = status;
this.inventoryDate = inventoryDate;
this.user = user;
this.inventoryReference = inventoryReference;
this.inventoryType = inventoryType;
this.ward = ward;
this.destination = destination;
this.reason = reason;
}

public Integer getId() {
return id;
}
Expand Down Expand Up @@ -223,4 +239,12 @@ public String getDestination() {
public void setDestination(String destination) {
this.destination = destination;
}

public String getReason() {
return reason;
}

public void setReason(String reason) {
this.reason = reason;
}
JantBogard marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Open Hospital (www.open-hospital.org)
* Copyright © 2006-2024 Informatici Senza Frontiere (info@informaticisenzafrontiere.org)
*
* Open Hospital is a free and open source software for healthcare data management.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* https://www.gnu.org/licenses/gpl-3.0-standalone.html
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.isf.medicalsinventory;
JantBogard marked this conversation as resolved.
Show resolved Hide resolved

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.within;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

import org.isf.medicalinventory.model.InventoryStatus;
import org.isf.medicalinventory.model.InventoryType;
import org.isf.medicalinventory.model.MedicalInventory;
import org.isf.utils.exception.OHException;
import org.isf.utils.time.TimeTools;
import org.isf.ward.model.Ward;

public class TestMedicalWardInventory {
private int id = 1;
private String status = InventoryStatus.draft.toString();
private LocalDateTime inventoryDate = TimeTools.getNow();
private String user = "admin";
private String inventoryReference = "REFERENCE";
private String inventoryType = InventoryType.ward.toString();
private String ward = "Z";
private String destination = "Z";
private String reason = "reason";

public MedicalInventory setup(Ward ward, boolean usingSet) throws OHException {
MedicalInventory medicalInventory;

if (usingSet) {
medicalInventory = new MedicalInventory();
setParameters(medicalInventory);
} else {
// create MedicalInventory with all parameters
medicalInventory = new MedicalInventory(id, status, inventoryDate, user, inventoryReference, inventoryType, ward.getCode(), destination, reason);
}
return medicalInventory;
}

public void setParameters(MedicalInventory medicalInventory) {
medicalInventory.setId(id);
medicalInventory.setStatus(status);
medicalInventory.setInventoryDate(inventoryDate);
medicalInventory.setUser(user);
medicalInventory.setInventoryReference(inventoryReference);
medicalInventory.setInventoryType(inventoryType);
medicalInventory.setWard(ward);
medicalInventory.setDestination(destination);
medicalInventory.setReason(reason);
}

public void check(MedicalInventory medicalInventory, int id) {
assertThat(medicalInventory.getId()).isEqualTo(id);
assertThat(medicalInventory.getStatus()).isEqualTo(status);
assertThat(medicalInventory.getInventoryDate()).isCloseTo(inventoryDate, within(1, ChronoUnit.SECONDS));
assertThat(medicalInventory.getUser()).isEqualTo(user);
assertThat(medicalInventory.getInventoryReference()).isEqualTo(inventoryReference);
assertThat(medicalInventory.getInventoryType()).isEqualTo(inventoryType);
assertThat(medicalInventory.getWard()).isEqualTo(ward);
assertThat(medicalInventory.getDestination()).isEqualTo(destination);
assertThat(medicalInventory.getReason()).isEqualTo(reason);
}
}
Loading