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

OLMIS-7989: Added Facility Import & Quick performance improvements #125

Merged
merged 6 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ dependencies {

compile 'net.sf.supercsv:super-csv:2.4.0'
compile 'net.sf.supercsv:super-csv-dozer:2.4.0'
compile 'io.craftsman:dozer-jdk8-support:1.0.6'

compile 'ca.uhn.hapi.fhir:hapi-fhir-client:3.7.0'
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-r4:3.7.0'
Expand Down Expand Up @@ -421,4 +422,4 @@ assemble {
build {
dependsOn check
dependsOn jacocoTestReport
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

import com.google.common.util.concurrent.MoreExecutors;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
Expand All @@ -27,6 +31,7 @@
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.transaction.Transactional;
Expand All @@ -39,6 +44,7 @@
import org.junit.Test;
import org.junit.contrib.java.lang.system.EnvironmentVariables;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.openlmis.referencedata.Application;
import org.openlmis.referencedata.domain.Code;
import org.openlmis.referencedata.domain.Dispensable;
Expand All @@ -55,17 +61,23 @@
import org.openlmis.referencedata.repository.ProgramRepository;
import org.openlmis.referencedata.repository.TradeItemRepository;
import org.openlmis.referencedata.service.export.DataImportService;
import org.openlmis.referencedata.service.export.OrderableImportPersister;
import org.openlmis.referencedata.service.export.ProgramOrderableImportPersister;
import org.openlmis.referencedata.service.export.TradeItemImportPersister;
import org.openlmis.referencedata.testbuilder.OrderableDataBuilder;
import org.openlmis.referencedata.testbuilder.OrderableDisplayCategoryDataBuilder;
import org.openlmis.referencedata.testbuilder.ProgramDataBuilder;
import org.openlmis.referencedata.testbuilder.ProgramOrderableDataBuilder;
import org.openlmis.referencedata.testbuilder.TradeItemDataBuilder;
import org.openlmis.referencedata.util.TransactionUtils;
import org.slf4j.profiler.Profiler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.util.Pair;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class, DataImportService.class})
Expand Down Expand Up @@ -203,16 +215,55 @@ public class DataImportServiceIntegrationTest {
@Autowired
private TradeItemRepository tradeItemRepository;

@Autowired
private OrderableImportPersister orderableImportPersister;

@Autowired
private ProgramOrderableImportPersister programOrderableImportPersister;

@Autowired
private TradeItemImportPersister tradeItemImportPersister;

@Mock
private Profiler profiler;

@Mock
private TransactionUtils transactionUtils;

@Before
public void setUp() {
environmentVariables.set("CURRENCY_CODE", "USD");
persistedProgram = createAndPersistProgram(PROGRAM_CODE);
persistedOrderableDisplayCategory =
createAndPersistOrderableDisplayCategory(ORDERABLE_DISPLAY_CATEGORY);

when(profiler.startNested(anyString())).thenReturn(profiler);
when(transactionUtils.runInOwnTransaction(any(Supplier.class)))
.thenAnswer(invocation -> ((Supplier) invocation.getArgument(0)).get());

ReflectionTestUtils.setField(
orderableImportPersister,
"importExecutorService",
MoreExecutors.newDirectExecutorService());
ReflectionTestUtils.setField(
programOrderableImportPersister,
"importExecutorService",
MoreExecutors.newDirectExecutorService());
ReflectionTestUtils.setField(
tradeItemImportPersister,
"importExecutorService",
MoreExecutors.newDirectExecutorService());

ReflectionTestUtils.setField(
orderableImportPersister, "transactionUtils", transactionUtils);
ReflectionTestUtils.setField(
programOrderableImportPersister, "transactionUtils", transactionUtils);
ReflectionTestUtils.setField(
tradeItemImportPersister, "transactionUtils", transactionUtils);
}

@Test
public void shouldImportOrderablesFromValidCsvFile() throws IOException {
public void shouldImportOrderablesFromValidCsvFile() throws IOException, InterruptedException {
// given
createAndPersistOrderable(ORDERABLE_CODE_1, TEST_NAME,
TEST_DISPENSABLE);
Expand All @@ -221,7 +272,7 @@ public void shouldImportOrderablesFromValidCsvFile() throws IOException {
ORDERABLE_CORRECT_HEADERS, ORDERABLES_FILE);

// when
List<BaseDto> result = dataImportService.importData(multipartFile);
List<BaseDto> result = dataImportService.importData(multipartFile, profiler);

// then check if result is present
assertNotNull(result);
Expand Down Expand Up @@ -249,7 +300,8 @@ public void shouldImportOrderablesFromValidCsvFile() throws IOException {
}

@Test
public void shouldImportProgramOrderablesFromValidCsvFile() throws IOException {
public void shouldImportProgramOrderablesFromValidCsvFile()
throws IOException, InterruptedException {
// given
Orderable persistedOrderable = createAndPersistOrderable(
ORDERABLE_CODE_1, TEST_NAME, TEST_DISPENSABLE);
Expand All @@ -262,7 +314,7 @@ public void shouldImportProgramOrderablesFromValidCsvFile() throws IOException {
PROGRAM_ORDERABLE_CORRECT_HEADERS, PROGRAM_ORDERABLES_FILE);

// when
List<BaseDto> result = dataImportService.importData(multipartFile);
List<BaseDto> result = dataImportService.importData(multipartFile, profiler);

// then check if result is present
assertNotNull(result);
Expand Down Expand Up @@ -290,7 +342,7 @@ public void shouldImportProgramOrderablesFromValidCsvFile() throws IOException {
}

@Test
public void shouldImportTradeItemFromValidCsvFile() throws IOException {
public void shouldImportTradeItemFromValidCsvFile() throws IOException, InterruptedException {
// given
final TradeItem persistedTradeItem1 = createAndPersistTradeItem(TEST_MANUFACTURER);
final TradeItem persistedTradeItem2 = createAndPersistTradeItem(TEST_MANUFACTURER);
Expand All @@ -310,7 +362,7 @@ public void shouldImportTradeItemFromValidCsvFile() throws IOException {
TRADE_ITEM_CORRECT_HEADERS, TRADE_ITEM_FILE);

// when
List<BaseDto> result = dataImportService.importData(multipartFile);
List<BaseDto> result = dataImportService.importData(multipartFile, profiler);

// then check if result is present
assertNotNull(result);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* 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.referencedata.service.export;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.util.concurrent.MoreExecutors;
import java.io.IOException;
import java.util.List;
import java.util.function.Supplier;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.openlmis.referencedata.Application;
import org.openlmis.referencedata.domain.GeographicLevel;
import org.openlmis.referencedata.dto.FacilityDto;
import org.openlmis.referencedata.repository.FacilityOperatorRepository;
import org.openlmis.referencedata.repository.FacilityTypeRepository;
import org.openlmis.referencedata.repository.GeographicLevelRepository;
import org.openlmis.referencedata.repository.GeographicZoneRepository;
import org.openlmis.referencedata.testbuilder.FacilityOperatorDataBuilder;
import org.openlmis.referencedata.testbuilder.FacilityTypeDataBuilder;
import org.openlmis.referencedata.testbuilder.GeographicLevelDataBuilder;
import org.openlmis.referencedata.testbuilder.GeographicZoneDataBuilder;
import org.openlmis.referencedata.util.TransactionUtils;
import org.slf4j.profiler.Profiler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class, DataImportService.class})
@ActiveProfiles({"test", "test-run"})
public class FacilityImportPersisterIntegrationTest {
@Autowired private FacilityTypeRepository facilityTypeRepository;
@Autowired private GeographicLevelRepository geographicLevelRepository;
@Autowired private GeographicZoneRepository geographicZoneRepository;
@Autowired private FacilityOperatorRepository facilityOperatorRepository;
@Autowired private FacilityImportPersister facilityImportPersister;
@Mock private TransactionUtils transactionUtils;

@Before
public void setup() {
ReflectionTestUtils.setField(
facilityImportPersister, "importExecutorService", MoreExecutors.newDirectExecutorService());
ReflectionTestUtils.setField(
facilityImportPersister, "transactionUtils", transactionUtils);
when(transactionUtils.runInOwnTransaction(any(Supplier.class)))
.thenAnswer(invocation -> ((Supplier) invocation.getArgument(0)).get());
}

@Test
@Transactional
public void shouldImportFacility() throws IOException, InterruptedException {
facilityTypeRepository.save(new FacilityTypeDataBuilder().withCode("TestType").buildAsNew());
final GeographicLevel geographicLevel =
geographicLevelRepository.save(new GeographicLevelDataBuilder().buildAsNew());
geographicZoneRepository.save(
new GeographicZoneDataBuilder()
.withCode("TestZone")
.withLevel(geographicLevel)
.buildAsNew());
facilityOperatorRepository.save(
new FacilityOperatorDataBuilder().withCode("TestOperator").buildAsNew());

final List<FacilityDto> facilityDtos =
facilityImportPersister.processAndPersist(
new ClassPathResource("/FacilityImportPersisterTest/facility.csv").getInputStream(),
mock(Profiler.class));

assertEquals(1, facilityDtos.size());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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.referencedata.service.export;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.util.concurrent.MoreExecutors;
import java.io.IOException;
import java.util.List;
import java.util.function.Supplier;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.openlmis.referencedata.Application;
import org.openlmis.referencedata.domain.FacilityType;
import org.openlmis.referencedata.domain.GeographicLevel;
import org.openlmis.referencedata.domain.GeographicZone;
import org.openlmis.referencedata.dto.SupportedProgramDto;
import org.openlmis.referencedata.repository.FacilityRepository;
import org.openlmis.referencedata.repository.FacilityTypeRepository;
import org.openlmis.referencedata.repository.GeographicLevelRepository;
import org.openlmis.referencedata.repository.GeographicZoneRepository;
import org.openlmis.referencedata.repository.ProgramRepository;
import org.openlmis.referencedata.testbuilder.FacilityDataBuilder;
import org.openlmis.referencedata.testbuilder.FacilityTypeDataBuilder;
import org.openlmis.referencedata.testbuilder.GeographicLevelDataBuilder;
import org.openlmis.referencedata.testbuilder.GeographicZoneDataBuilder;
import org.openlmis.referencedata.testbuilder.ProgramDataBuilder;
import org.openlmis.referencedata.util.TransactionUtils;
import org.slf4j.profiler.Profiler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class, DataImportService.class})
@ActiveProfiles({"test", "test-run"})
public class SupportedProgramImportPersisterIntegrationTest {
@Autowired private GeographicLevelRepository geographicLevelRepository;
@Autowired private GeographicZoneRepository geographicZoneRepository;
@Autowired private FacilityTypeRepository facilityTypeRepository;
@Autowired private ProgramRepository programRepository;
@Autowired private FacilityRepository facilityRepository;
@Autowired private SupportedProgramImportPersister supportedProgramImportPersister;
@Mock private TransactionUtils transactionUtils;

@Before
public void setup() {
ReflectionTestUtils.setField(
supportedProgramImportPersister,
"importExecutorService",
MoreExecutors.newDirectExecutorService());
ReflectionTestUtils.setField(
supportedProgramImportPersister, "transactionUtils", transactionUtils);
when(transactionUtils.runInOwnTransaction(any(Supplier.class)))
.thenAnswer(invocation -> ((Supplier) invocation.getArgument(0)).get());
}

@Test
@Transactional
public void shouldImportSupportedProgram() throws IOException, InterruptedException {
final GeographicLevel geographicLevel =
geographicLevelRepository.save(new GeographicLevelDataBuilder().buildAsNew());
final GeographicZone geographicZone =
geographicZoneRepository.save(
new GeographicZoneDataBuilder()
.withCode("TestZone")
.withLevel(geographicLevel)
.buildAsNew());
final FacilityType facilityType =
facilityTypeRepository.save(
new FacilityTypeDataBuilder().withCode("TestType").buildAsNew());
facilityRepository.save(
new FacilityDataBuilder()
.withCode("TestFacility1")
.withGeographicZone(geographicZone)
.withType(facilityType)
.withOperator(null)
.buildAsNew());
programRepository.save(new ProgramDataBuilder().withCode("TestProgram1").buildAsNew());

final List<SupportedProgramDto> supportedProgramDtos =
supportedProgramImportPersister.processAndPersist(
new ClassPathResource(
"/SupportedProgramImportPersisterIntegrationTest/supportedProgram.csv")
.getInputStream(),
mock(Profiler.class));

assertEquals(1, supportedProgramDtos.size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,4 @@ private String getPathAsString() {
.path(MESSAGE_KEY);
}

}
}
Loading
Loading