Skip to content

Commit

Permalink
avniproject/avni-product#1531 | Handle locationMode and locationHiera…
Browse files Browse the repository at this point in the history
…rchy input params during locations sample file download
  • Loading branch information
himeshr committed May 31, 2024
1 parent 8eed73d commit 788430e
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,15 @@ public void setLocationUploadMode(String locationUploadMode) {
this.locationUploadMode = locationUploadMode;
}

private enum LocationUploadMode {
public enum LocationUploadMode {
relaxed, strict;

public static boolean isRelaxedMode(String mode) {
return mode == null || LocationUploadMode.valueOf(mode).equals(relaxed);
}

public static boolean isRelaxedMode(LocationUploadMode mode) {
return mode.equals(relaxed);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.avni.server.service;

import org.avni.server.importer.batch.csv.writer.header.LocationHeaders;

import java.util.Collections;

public interface ImportLocationsConstants {
String STRING_CONSTANT_NEW_LINE = "\n";
String STRING_CONSTANT_EMPTY_STRING = "";
String STRING_PLACEHOLDER_BLOCK = "\"%s\",";
String STRING_3_PLACEHOLDER_BLOCK = String.join("", Collections.nCopies(3, STRING_PLACEHOLDER_BLOCK));
String Example = "Ex: ";
String ALLOWED_VALUES = "Allowed values: ";
String COLUMN_NAME_GPS_COORDINATES = LocationHeaders.gpsCoordinates;
String COLUMN_NAME_LOCATION_WITH_FULL_HIERARCHY = "Location with full hierarchy";
String COLUMN_NAME_NEW_LOCATION_NAME = "New location name";
String COLUMN_NAME_PARENT_LOCATION_WITH_FULL_HIERARCHY = "Parent location with full hierarchy";
String LOCATION_WITH_FULL_HIERARCHY_DESCRIPTION = "Can be found from Admin -> Locations -> Click Export. Used to specify which location's fields need to be updated. mandatory field";
String NEW_LOCATION_NAME_DESCRIPTION = "Enter new name here ONLY if it needs to be updated";
String PARENT_LOCATION_WITH_FULL_HIERARCHY_DESCRIPTION = "Hierarchy of parent location that should contain the child location";
String LOCATION_WITH_FULL_HIERARCHY_EXAMPLE = "PHC B, Sub B, Vil B";
String NEW_LOCATION_NAME_EXAMPLE = "Vil C";
String PARENT_LOCATION_WITH_FULL_HIERARCHY_EXAMPLE = "PHC C, Sub C";
String GPS_COORDINATES_EXAMPLE = "Ex: 23.45,43.85";
String ENTER_YOUR_DATA_STARTING_HERE = "Enter your data starting here";
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,23 @@
import org.avni.server.domain.*;
import org.avni.server.domain.Locale;
import org.avni.server.framework.security.UserContextHolder;
import org.avni.server.importer.batch.csv.writer.LocationWriter;
import org.avni.server.importer.batch.csv.writer.ProgramEnrolmentWriter;
import org.avni.server.importer.batch.csv.writer.header.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class ImportService {
public class ImportService implements ImportLocationsConstants{

public static final String GPS_COORDINATES = ",\""+LocationHeaders.gpsCoordinates+"\",";
public static final String GPS_COORDINATES_EXAMPLE = ",\"Ex: 23.45,43.85\",";
public static final String STRING_CONSTANT_NEW_LINE = "\n";
private final SubjectTypeRepository subjectTypeRepository;
private final FormMappingRepository formMappingRepository;
private static final Logger logger = LoggerFactory.getLogger(ProgramEnrolmentWriter.class);
Expand Down Expand Up @@ -134,10 +133,6 @@ public String getSampleFile(String uploadType) {
String[] uploadSpec = uploadType.split("---");
String response = "";

if (uploadType.equals("locations")) {
return getLocationsSampleFile();
}

if (uploadType.equals("usersAndCatchments")) {
return getUsersAndCatchmentsSampleFile();
}
Expand Down Expand Up @@ -169,22 +164,32 @@ public String getSampleFile(String uploadType) {
throw new UnsupportedOperationException(String.format("Sample file format for %s not supported", uploadType));
}

private String getLocationsSampleFile() {
public String getLocationsSampleFile(LocationWriter.LocationUploadMode locationUploadMode, String locationHierarchy) {
StringBuilder sampleFileBuilder = new StringBuilder();
List<AddressLevelType> addressLevelTypes = null;
try {
List<AddressLevelType> addressLevelTypes = getAddressLevelTypesForCreateModeSingleHierarchy();
if (LocationWriter.LocationUploadMode.isRelaxedMode(locationUploadMode)) {
addressLevelTypes = getAddressLevelTypesForCreateModeSingleHierarchy(locationHierarchy);
}
List<FormElement> formElementNamesForLocationTypeFormElements = getFormElementNamesForLocationTypeForms();
appendHeaderRowForLocations(sampleFileBuilder, addressLevelTypes, formElementNamesForLocationTypeFormElements);
appendDescriptionForLocations(sampleFileBuilder, addressLevelTypes, formElementNamesForLocationTypeFormElements);
appendHeaderRowForLocations(sampleFileBuilder, locationUploadMode, addressLevelTypes, formElementNamesForLocationTypeFormElements);
appendDescriptionForLocations(sampleFileBuilder, locationUploadMode, addressLevelTypes, formElementNamesForLocationTypeFormElements);
appendExamplesForLocations(sampleFileBuilder, locationUploadMode);
} catch (Exception e) {
throw new RuntimeException(e);
}
return sampleFileBuilder.toString();
}

private List<AddressLevelType> getAddressLevelTypesForCreateModeSingleHierarchy() {
private List<AddressLevelType> getAddressLevelTypesForCreateModeSingleHierarchy(String locationHierarchy) throws Exception {
if(!StringUtils.hasText(locationHierarchy)) {
throw new Exception(String.format("Invalid value specified for locationHierarchy: %s", locationHierarchy));
}
List<Long> selectedLocationHierarchy = Arrays.stream(locationHierarchy.split("\\."))
.map(Long::parseLong).collect(Collectors.toList());
return addressLevelTypeRepository.findAllByIsVoidedFalse().stream()
.sorted(Comparator.comparingDouble(AddressLevelType::getLevel).reversed())
.filter(alt -> selectedLocationHierarchy.contains(alt.getId()))
.collect(Collectors.toList());
}

Expand Down Expand Up @@ -215,23 +220,42 @@ private List<FormElement> createDecisionFormElement(Set<Concept> concepts) {
}).collect(Collectors.toList());
}

private void appendHeaderRowForLocations(StringBuilder sampleFileBuilder, List<AddressLevelType> addressLevelTypes,
private void appendHeaderRowForLocations(StringBuilder sampleFileBuilder, LocationWriter.LocationUploadMode locationUploadMode, List<AddressLevelType> addressLevelTypes,
List<FormElement> formElementNamesForLocationTypeFormElements) {
sampleFileBuilder.append(addressLevelTypes.stream()
.map(alt -> String.format("\"%s\"", alt.getName())).collect(Collectors.joining(",")));
sampleFileBuilder.append(GPS_COORDINATES);
if (LocationWriter.LocationUploadMode.isRelaxedMode(locationUploadMode)) {
sampleFileBuilder.append(addressLevelTypes.stream()
.map(alt -> String.format(STRING_PLACEHOLDER_BLOCK, alt.getName())).collect(Collectors.joining(STRING_CONSTANT_EMPTY_STRING)));
} else {
sampleFileBuilder.append(String.format(STRING_3_PLACEHOLDER_BLOCK, COLUMN_NAME_LOCATION_WITH_FULL_HIERARCHY,
COLUMN_NAME_NEW_LOCATION_NAME, COLUMN_NAME_PARENT_LOCATION_WITH_FULL_HIERARCHY));
}
sampleFileBuilder.append(String.format(STRING_PLACEHOLDER_BLOCK, COLUMN_NAME_GPS_COORDINATES));
sampleFileBuilder.append(formElementNamesForLocationTypeFormElements.stream()
.map(fe -> String.format("\"%s\"", fe.getName())).collect(Collectors.joining(",")));
.map(fe -> String.format(STRING_PLACEHOLDER_BLOCK, fe.getName())).collect(Collectors.joining(STRING_CONSTANT_EMPTY_STRING)));
}

private void appendDescriptionForLocations(StringBuilder sampleFileBuilder, List<AddressLevelType> addressLevelTypes,
private void appendDescriptionForLocations(StringBuilder sampleFileBuilder, LocationWriter.LocationUploadMode locationUploadMode, List<AddressLevelType> addressLevelTypes,
List<FormElement> formElementNamesForLocationTypeFormElements) {
sampleFileBuilder.append(STRING_CONSTANT_NEW_LINE).append(addressLevelTypes.stream()
.map(alt -> String.format("\"Ex: %s1\"", alt.getName())).collect(Collectors.joining(",")));
sampleFileBuilder.append(GPS_COORDINATES_EXAMPLE);
if (LocationWriter.LocationUploadMode.isRelaxedMode(locationUploadMode)) {
sampleFileBuilder.append(STRING_CONSTANT_NEW_LINE).append(addressLevelTypes.stream()
.map(alt -> String.format(STRING_PLACEHOLDER_BLOCK, Example +alt.getName())).collect(Collectors.joining(STRING_CONSTANT_EMPTY_STRING)));
} else {
sampleFileBuilder.append(STRING_CONSTANT_NEW_LINE).append(String.format(STRING_3_PLACEHOLDER_BLOCK, LOCATION_WITH_FULL_HIERARCHY_DESCRIPTION,
NEW_LOCATION_NAME_DESCRIPTION, PARENT_LOCATION_WITH_FULL_HIERARCHY_DESCRIPTION));
}
sampleFileBuilder.append(String.format(STRING_PLACEHOLDER_BLOCK, GPS_COORDINATES_EXAMPLE));
sampleFileBuilder.append(formElementNamesForLocationTypeFormElements.stream()
.map(fe -> String.format("\"Allowed values: %s\"", conceptService.getSampleValuesForSyncConcept(fe.getConcept())))
.collect(Collectors.joining(",")));
.map(fe -> String.format(STRING_PLACEHOLDER_BLOCK, ALLOWED_VALUES +conceptService.getSampleValuesForSyncConcept(fe.getConcept())))
.collect(Collectors.joining(STRING_CONSTANT_EMPTY_STRING)));
}

private void appendExamplesForLocations(StringBuilder sampleFileBuilder, LocationWriter.LocationUploadMode locationUploadMode) {
if (LocationWriter.LocationUploadMode.isRelaxedMode(locationUploadMode)) {
sampleFileBuilder.append(STRING_CONSTANT_NEW_LINE).append(ENTER_YOUR_DATA_STARTING_HERE);
} else {
sampleFileBuilder.append(STRING_CONSTANT_NEW_LINE).append(String.format(STRING_3_PLACEHOLDER_BLOCK, LOCATION_WITH_FULL_HIERARCHY_EXAMPLE,
NEW_LOCATION_NAME_EXAMPLE, PARENT_LOCATION_WITH_FULL_HIERARCHY_EXAMPLE));
}
}

private String getUsersAndCatchmentsSampleFile() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import org.avni.server.domain.accessControl.PrivilegeType;
import org.avni.server.framework.security.UserContextHolder;
import org.avni.server.importer.batch.JobService;
import org.avni.server.importer.batch.csv.writer.LocationWriter;
import org.avni.server.service.*;
import org.avni.server.service.accessControl.AccessControlService;
import org.avni.server.util.BadRequestError;
import org.avni.server.web.util.ErrorBodyBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -27,6 +29,7 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

Expand Down Expand Up @@ -75,11 +78,24 @@ public ImportController(JobService jobService,
}

@RequestMapping(value = "/web/importSample", method = RequestMethod.GET)
public void getSampleImportFile(@RequestParam String uploadType, HttpServletResponse response) throws IOException {
public void getSampleImportFile(@RequestParam String uploadType,
@RequestParam(value = "locationHierarchy", required = false) String locationHierarchy,
@RequestParam(value = "locationUploadMode", required = false) LocationWriter.LocationUploadMode locationUploadMode,
HttpServletResponse response) throws IOException {
response.setContentType("text/csv");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + uploadType + ".csv\"");
response.getWriter().write(importService.getSampleFile(uploadType));
if (uploadType.equals("locations")) {
if(!StringUtils.hasText(locationHierarchy)) {
throw new BadRequestError("Invalid value specified for request param \"locationHierarchy\": "+ locationHierarchy);
}
if(locationUploadMode == null) {
throw new BadRequestError("Missing value for request param \"locationUploadMode\"");
}
response.getWriter().write(importService.getLocationsSampleFile(locationUploadMode, locationHierarchy));
} else {
response.getWriter().write(importService.getSampleFile(uploadType));
}
}

@RequestMapping(value = "/web/importTypes", method = RequestMethod.GET)
Expand Down

0 comments on commit 788430e

Please sign in to comment.