Skip to content

Commit

Permalink
OAM-48: Added event validation and assignments filter for Wards/Servi…
Browse files Browse the repository at this point in the history
…ces (#51)

* OAM-48: Added event validation for Wards/Services

* OAM-48: Added destination/source filter for Wards/Services

* OAM-48: Removed unnecessary lines
  • Loading branch information
sradziszewski committed Jun 13, 2024
1 parent 6bba589 commit 1ad8b8f
Show file tree
Hide file tree
Showing 12 changed files with 346 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
import static org.openlmis.stockmanagement.i18n.MessageKeys.ERROR_REASON_ASSIGNMENT_NOT_FOUND;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ public abstract class MessageKeys {
EVENT_ERROR_PREFIX + ".reasonFreeText.notAllowed";
public static final String ERROR_STOCK_EVENT_ORDERABLE_DISABLED_VVM =
EVENT_ERROR_PREFIX + ".orderable.disabled.vvm";
public static final String ERROR_DESTINATION_MUST_BE_WARD_SERVICE_OF_FACILITY =
EVENT_ERROR_PREFIX + ".destination.must.be.wardService.of.facility";
//stock events creation: mandatory fields
public static final String ERROR_EVENT_OCCURRED_DATE_INVALID = EVENT_ERROR_PREFIX
+ ".occurredDate.invalid";
Expand Down Expand Up @@ -249,7 +251,10 @@ public abstract class MessageKeys {
PHYSICAL_INVENTORY_ERROR_PREFIX + ".draft.exists";
public static final String ERROR_PHYSICAL_INVENTORY_DRAFT_SUBMIT =
PHYSICAL_INVENTORY_ERROR_PREFIX + ".draft.submit";

private static final String NODE_ERROR_PREFIX = ERROR_PREFIX + ".node";
//node
public static final String ERROR_NODE_NOT_FOUND =
NODE_ERROR_PREFIX + ".notFound";
public static final String ERROR_SIZE_NULL
= ERROR_PREFIX + ".pageable.size.null";
public static final String ERROR_SIZE_NOT_POSITIVE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,21 @@ private List<ValidSourceDestinationDto> createAssignmentDto(
return true;
}
})
.filter(assignment -> {
// check if assignment facility is type Ward/Service AND is in the same zone as facility
if (assignment.getNode().isRefDataFacility()) {
FacilityDto assignmentFacility =
facilitiesById.get(assignment.getNode().getReferenceId());
if (assignmentFacility.getType().getCode().equals("WS")) {
return assignmentFacility.getGeographicZone().getId()
.equals(facility.getGeographicZone().getId());
} else {
return true;
}
} else {
return true;
}
})
.filter(assignment -> !assignment.getNode().isRefDataFacility()
|| hasGeoAffinity(assignment, facility, facilitiesById))
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.openlmis.stockmanagement.extension.point.FreeTextValidator;
import org.openlmis.stockmanagement.extension.point.UnpackKitValidator;
import org.openlmis.stockmanagement.validators.ApprovedOrderableValidator;
import org.openlmis.stockmanagement.validators.FacilityValidator;
import org.openlmis.stockmanagement.validators.LotValidator;
import org.openlmis.stockmanagement.validators.MandatoryFieldsValidator;
import org.openlmis.stockmanagement.validators.OrderableLotUnitDuplicationValidator;
Expand Down Expand Up @@ -83,6 +84,9 @@ public class StockEventValidationsService {
@Autowired
private UnitOfOrderableValidator unitOfOrderableValidator;

@Autowired
private FacilityValidator facilityValidator;

/**
* Validate stock event with permission service and all validators.
*
Expand All @@ -101,6 +105,7 @@ public void validate(StockEventDto stockEventDto) {
destinationGeoLevelAffinityValidator.validate(stockEventDto);
stockEventVvmValidator.validate(stockEventDto);
unitOfOrderableValidator.validate(stockEventDto);
facilityValidator.validate(stockEventDto);

AdjustmentReasonValidator adjustmentReasonValidator = extensionManager.getExtension(
ExtensionPointId.ADJUSTMENT_REASON_POINT_ID, AdjustmentReasonValidator.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* This program is part of the OpenLMIS logistics management information system platform software.
* Copyright © 2017 VillageReach
*
* This program is free software: you can redistribute it and/or modify it under the terms
* of the GNU Affero General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* 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 Affero General Public License for more details. You should have received a copy of
* the GNU Affero General Public License along with this program. If not, see
* http://www.gnu.org/licenses.  For additional information contact [email protected].
*/

package org.openlmis.stockmanagement.validators;

import static org.openlmis.stockmanagement.i18n.MessageKeys.ERROR_DESTINATION_MUST_BE_WARD_SERVICE_OF_FACILITY;
import static org.openlmis.stockmanagement.i18n.MessageKeys.ERROR_NODE_NOT_FOUND;

import org.openlmis.stockmanagement.domain.sourcedestination.Node;
import org.openlmis.stockmanagement.dto.StockEventDto;
import org.openlmis.stockmanagement.dto.StockEventLineItemDto;
import org.openlmis.stockmanagement.dto.referencedata.FacilityDto;
import org.openlmis.stockmanagement.exception.ResourceNotFoundException;
import org.openlmis.stockmanagement.exception.ValidationMessageException;
import org.openlmis.stockmanagement.repository.NodeRepository;
import org.openlmis.stockmanagement.service.referencedata.FacilityReferenceDataService;
import org.openlmis.stockmanagement.util.Message;
import org.slf4j.profiler.Profiler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component(value = "FacilityValidator")
public class FacilityValidator implements StockEventValidator {

@Autowired
private FacilityReferenceDataService facilityService;

@Autowired
private NodeRepository nodeRepository;

@Override
public void validate(StockEventDto stockEventDto) {
XLOGGER.entry(stockEventDto);

Profiler profiler = new Profiler("FACILITY_VALIDATOR");
profiler.setLogger(XLOGGER);

if (stockEventDto.isPhysicalInventory() || stockEventDto.getLineItems().isEmpty()) {
return;
}

FacilityDto facility = facilityService.findOne(stockEventDto.getFacilityId());
for (StockEventLineItemDto lineItem : stockEventDto.getLineItems()) {
if (lineItem.getDestinationId() != null) {
Node node = nodeRepository.findById(lineItem.getDestinationId())
.orElseThrow(() -> new ResourceNotFoundException(
new Message(ERROR_NODE_NOT_FOUND, lineItem.getDestinationId())));
if (node.isRefDataFacility()) {
FacilityDto destinationFacility = facilityService.findOne(node.getReferenceId());
if (destinationFacility.getType().getCode().equals("WS")
&& !destinationFacility.getGeographicZone().getId()
.equals(facility.getGeographicZone().getId())) {
throw new ValidationMessageException(
new Message(ERROR_DESTINATION_MUST_BE_WARD_SERVICE_OF_FACILITY));
}
}
}
}

profiler.stop().log();
XLOGGER.exit(stockEventDto);
}

}
2 changes: 2 additions & 0 deletions src/main/resources/api-definition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ traits:

403:
description: User does not have permission to create stock events for given facility and program.
headers:
Keep-Alive:
body:
application/json:
schema: localizedMessage
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ stockmanagement.error.event.no.lineItems=No line items were provided. {0}
stockmanagement.error.event.sourceAndDestination.bothPresent=Source {0} and destination {1} should not both be present.
stockmanagement.error.event.source.not.in.validList=Source {0} is not in the valid sources list.
stockmanagement.error.event.destination.not.in.validList=Destination {0} is not in the valid destinations list.
stockmanagement.error.event.destination.must.be.wardService.of.facility=Products can only be issued between wards/services of a given facility.
#stock event creation: adjustment reason
stockmanagement.error.event.adjustment.quantity.invalid=Stock Adjustment quantity must not be negative.
stockmanagement.error.event.adjustment.reason.type.invalid=Reason type {0} is not valid for this adjustment event.
Expand Down Expand Up @@ -121,6 +122,8 @@ stockmanagement.error.reporting.file.empty=Empty file
stockmanagement.reason.physicalInventory.credit=Overstock
stockmanagement.reason.physicalInventory.debit=Understock
stockmanagement.reason.physicalInventory.balance_adjustment=Balance adjustment
#node
stockmanagement.error.node.notFound=Node not found for id: {0}
#notification
stockmanagement.email.stockout.subject=STOCKOUT Action Required: ${facilityName}, ${orderableName}
stockmanagement.email.stockout.content=Dear ${username}:\n\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,7 @@ private GeographicZoneDto generateGeographicZone(UUID districtLevelId, UUID regi
private FacilityDto createFacilityDtoWithFacilityType(UUID facilityId, UUID facilityTypeId) {
FacilityTypeDto facilityDto = new FacilityTypeDto();
facilityDto.setId(facilityTypeId);
facilityDto.setCode("TEST");
return FacilityDto.builder()
.id(facilityId)
.type(facilityDto)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.openlmis.stockmanagement.validators.DefaultAdjustmentReasonValidator;
import org.openlmis.stockmanagement.validators.DefaultFreeTextValidator;
import org.openlmis.stockmanagement.validators.DefaultUnpackKitValidator;
import org.openlmis.stockmanagement.validators.FacilityValidator;
import org.openlmis.stockmanagement.validators.LotValidator;
import org.openlmis.stockmanagement.validators.MandatoryFieldsValidator;
import org.openlmis.stockmanagement.validators.OrderableLotUnitDuplicationValidator;
Expand Down Expand Up @@ -108,6 +109,9 @@ public class StockEventValidationsServiceTest {
@Mock
private UnitOfOrderableValidator unitOfOrderableValidator;

@Mock
private FacilityValidator facilityValidator;

@Before
public void setUp() throws Exception {
//make real validators do nothing because
Expand All @@ -127,6 +131,7 @@ public void setUp() throws Exception {
doNothing().when(physicalInventoryReasonsValidator).validate(any(StockEventDto.class));
doNothing().when(unpackKitValidator).validate(any(StockEventDto.class));
doNothing().when(unitOfOrderableValidator).validate(any(StockEventDto.class));
doNothing().when(facilityValidator).validate(any(StockEventDto.class));
when(extensionManager
.getExtension(ExtensionPointId.ADJUSTMENT_REASON_POINT_ID, AdjustmentReasonValidator.class))
.thenReturn(adjustmentReasonValidator);
Expand Down Expand Up @@ -182,4 +187,4 @@ public void shouldNotRunNextValidatorIfPreviousValidatorFailed() throws Exceptio
}
}

}
}
Loading

0 comments on commit 1ad8b8f

Please sign in to comment.