Skip to content

Commit

Permalink
Merge branch '10.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
petmongrels committed Sep 17, 2024
2 parents f26b6fc + 3472068 commit e9f37b0
Show file tree
Hide file tree
Showing 50 changed files with 757 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

@NoRepositoryBean
public interface AvniJpaRepository<T, ID> extends JpaRepository<T, ID> {

@Override
@RestResource(exported = false)
<S extends T> S save(S entity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.avni.server.domain.CHSEntity;
import org.avni.server.domain.Concept;
import org.joda.time.DateTime;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.repository.NoRepositoryBean;

Expand Down Expand Up @@ -76,4 +77,10 @@ default void voidEntity(Long id) {
entity.setVoided(true);
this.save(entity);
}

boolean existsByLastModifiedDateTimeGreaterThan(Date lastModifiedDateTime);

default boolean existsByLastModifiedDateTimeGreaterThan(DateTime lastModifiedDateTime) {
return existsByLastModifiedDateTimeGreaterThan(lastModifiedDateTime == null ? null : lastModifiedDateTime.toDate());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@Repository
@RepositoryRestResource(collectionResourceRel = "card", path = "card")
public interface CardRepository extends ReferenceDataRepository<ReportCard>, FindByLastModifiedDateTime<ReportCard>, JpaSpecificationExecutor<ReportCard> {
public interface CardRepository extends ReferenceDataRepository<ReportCard>, JpaSpecificationExecutor<ReportCard>, EndOfLife1EndpointRepository<ReportCard> {

@Query("select c.name from ReportCard c where c.isVoided = false")
List<String> getAllNames();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@

@Repository
@RepositoryRestResource(collectionResourceRel = "dashboardFilter", path = "dashboardFilter")
public interface DashboardFilterRepository extends ReferenceDataRepository<DashboardFilter>, FindByLastModifiedDateTime<DashboardFilter>, JpaSpecificationExecutor<DashboardFilter> {
public interface DashboardFilterRepository extends ReferenceDataRepository<DashboardFilter>, JpaSpecificationExecutor<DashboardFilter>, EndOfLife1EndpointRepository<DashboardFilter> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@

@Repository
@RepositoryRestResource(collectionResourceRel = "dashboard", path = "dashboard")
public interface DashboardRepository extends ReferenceDataRepository<Dashboard>, FindByLastModifiedDateTime<Dashboard>, JpaSpecificationExecutor<Dashboard> {

public interface DashboardRepository extends ReferenceDataRepository<Dashboard>, JpaSpecificationExecutor<Dashboard>, EndOfLife1EndpointRepository<Dashboard> {
@Query("select d.name from Dashboard d where d.isVoided = false")
List<String> getAllNames();

List<Dashboard> findAllByIsVoidedFalseOrderByName();

Dashboard findByUuidAndOrganisationIdAndIsVoidedFalse(String uuid, Long organisationId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

@Repository
@RepositoryRestResource(collectionResourceRel = "dashboardSectionCardMapping", path = "dashboardSectionCardMapping")
public interface DashboardSectionCardMappingRepository extends ReferenceDataRepository<DashboardSectionCardMapping>, FindByLastModifiedDateTime<DashboardSectionCardMapping> {
public interface DashboardSectionCardMappingRepository extends ReferenceDataRepository<DashboardSectionCardMapping>, EndOfLife1EndpointRepository<DashboardSectionCardMapping> {

default DashboardSectionCardMapping findByName(String name) {
throw new UnsupportedOperationException("No field 'name' in FormMapping");
Expand All @@ -18,5 +18,4 @@ default DashboardSectionCardMapping findByNameIgnoreCase(String name) {
}

DashboardSectionCardMapping findByCardIdAndDashboardSectionAndIsVoidedFalse(Long id, DashboardSection section);

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@

@Repository
@RepositoryRestResource(collectionResourceRel = "dashboardSection", path = "dashboardSection")
public interface DashboardSectionRepository extends ReferenceDataRepository<DashboardSection>, FindByLastModifiedDateTime<DashboardSection>, JpaSpecificationExecutor<DashboardSection> {

public interface DashboardSectionRepository extends ReferenceDataRepository<DashboardSection>, JpaSpecificationExecutor<DashboardSection>, EndOfLife1EndpointRepository<DashboardSection> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.avni.server.dao;

import org.avni.server.domain.CHSEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RestResource;
import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;

/*
* This is a marker interface for all the repositories that are used to fetch entities with old endpoints that do not serve new data after configured date.
* Please also see org.avni.server.framework.sync.MetadataResourceInterceptor.endOfLifeEndpoints1
* https://github.com/avniproject/avni-server/issues/782
* same thing also done in StandardReportCardTypeRepository.java
*/
@NoRepositoryBean
public interface EndOfLife1EndpointRepository<T extends CHSEntity> {
@RestResource(path = "lastModified", rel = "lastModified")
Page<T> findByLastModifiedDateTimeIsGreaterThanEqualAndLastModifiedDateTimeLessThanEqualOrderByLastModifiedDateTimeAscIdAsc(
@Param("lastModifiedDateTime") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Date lastModifiedDateTime,
@Param("now") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Date now,
Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,4 @@ default Page<T> findByLastModifiedDateTimeIsBetweenOrderByLastModifiedDateTimeAs
Pageable pageable) {
return findByLastModifiedDateTimeIsBetweenOrderByLastModifiedDateTimeAscIdAsc(CHSEntity.toDate(lastModifiedDateTime), CHSEntity.toDate(now), pageable);
}

boolean existsByLastModifiedDateTimeGreaterThan(@Param("lastModifiedDateTime") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Date lastModifiedDateTime);

default boolean existsByLastModifiedDateTimeGreaterThan(DateTime lastModifiedDateTime) {
return existsByLastModifiedDateTimeGreaterThan(lastModifiedDateTime == null ? null : lastModifiedDateTime.toDate());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@

@Repository
@RepositoryRestResource(collectionResourceRel = "groupDashboard", path = "groupDashboard")

public interface GroupDashboardRepository extends ReferenceDataRepository<GroupDashboard>, FindByLastModifiedDateTime<GroupDashboard> {

public interface GroupDashboardRepository extends ReferenceDataRepository<GroupDashboard>, EndOfLife1EndpointRepository<GroupDashboard> {
default GroupDashboard findByName(String name) {
throw new UnsupportedOperationException("No field 'name' in GroupDashboard");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.avni.server.dao;

import org.avni.server.domain.StandardReportCardType;
import org.avni.server.domain.StandardReportCardTypeType;
import org.avni.server.domain.app.dashboard.DashboardFilter;
import org.joda.time.DateTime;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -11,6 +13,7 @@
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Set;

@Repository
@RepositoryRestResource(collectionResourceRel = "standardReportCardType", path = "standardReportCardType")
Expand All @@ -27,5 +30,5 @@ Page<StandardReportCardType> findByLastModifiedDateTimeIsBetweenOrderByLastModif

boolean existsByLastModifiedDateTimeGreaterThan(DateTime lastModifiedDateTime);

List<StandardReportCardType> findAllByNameIn(List<String> defaultDashboardStandardCardTypeNames);
List<StandardReportCardType> findAllByTypeIn(Set<StandardReportCardTypeType> defaultDashboardStandardCardTypeTypes);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package org.avni.server.domain;

import javax.persistence.*;
import javax.validation.constraints.NotNull;

import org.hibernate.annotations.BatchSize;
import org.joda.time.DateTime;

import javax.persistence.*;
import javax.validation.constraints.NotNull;

@Entity
@BatchSize(size = 100)
public class StandardReportCardType {
Expand All @@ -28,6 +28,10 @@ public class StandardReportCardType {
private DateTime createdDateTime;
@Column
private DateTime lastModifiedDateTime;
@Column
@NotNull
@Enumerated(EnumType.STRING)
private StandardReportCardTypeType type;

public Long getId() {
return id;
Expand Down Expand Up @@ -84,4 +88,12 @@ public DateTime getLastModifiedDateTime() {
public void setLastModifiedDateTime(DateTime lastModifiedDateTime) {
this.lastModifiedDateTime = lastModifiedDateTime;
}

public @NotNull StandardReportCardTypeType getType() {
return type;
}

public void setType(@NotNull StandardReportCardTypeType type) {
this.type = type;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.avni.server.domain;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public enum StandardReportCardTypeType {
PendingApproval,
Approved,
Rejected,
ScheduledVisits,
OverdueVisits,
Total,
Comments,
Tasks,
CallTasks,
OpenSubjectTasks,
DueChecklist,
RecentRegistrations,
RecentEnrolments,
RecentVisits;

private final static List<StandardReportCardTypeType> RecentCardTypes = new ArrayList<StandardReportCardTypeType>() {{
addAll(Arrays.asList(RecentEnrolments, RecentVisits, RecentRegistrations));
}};

public boolean isRecentStandardReportCardType() {
return RecentCardTypes.contains(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public static AvniAccessException createNoPrivilegeException(PrivilegeType privi
}

public static AvniAccessException createForNotAdmin(User user) {
return new AvniAccessException(String.format("User doesn't have privilege of type: %s", user.getUuid()));
return new AvniAccessException("User is not admin");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,33 @@
import org.joda.time.format.ISODateTimeFormat;
import org.avni.server.util.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;

@Component
public class MetadataResourceInterceptor extends HandlerInterceptorAdapter {
private final UserUtil userUtil;

private static final HashSet<String> endOfLifeEndpoints1 = new HashSet<String>() {{
add("/dashboardFilter/search/lastModified");
add("/card/search/lastModified");
add("/dashboardSection/search/lastModified");
add("/dashboardSectionCardMapping/search/lastModified");
add("/dashboard/search/lastModified");
add("/groupDashboard/search/lastModified");
}};

@Value("${avni.endpoints.endOfLife.1}")
private String endpointEndOfLife1;

@Autowired
public MetadataResourceInterceptor(UserUtil userUtil) {
this.userUtil = userUtil;
Expand All @@ -26,7 +42,15 @@ public MetadataResourceInterceptor(UserUtil userUtil) {
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object object) throws Exception {
if (request.getMethod().equals(RequestMethod.GET.name())) {
((MutableRequestWrapper) request).addParameter("now", new DateTime().toString(ISODateTimeFormat.dateTime()));
DateTime now = new DateTime();
if (endOfLifeEndpoints1.contains(request.getServletPath())) {
Date endOfLife1Date = new SimpleDateFormat("yyyy-MM-dd").parse(endpointEndOfLife1);
if (new Date().after(endOfLife1Date)) {
now = new DateTime(endOfLife1Date);
}
}

((MutableRequestWrapper) request).addParameter("now", now.toString(ISODateTimeFormat.dateTime()));
User user = UserContextHolder.getUser();
if (user == null) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "User not available from UserContext. Check for Auth errors");
Expand All @@ -36,5 +60,4 @@ public boolean preHandle(HttpServletRequest request,
}
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public void addParameter(String name, String value) {
values = new String[0];
}
List<String> list = new ArrayList<String>(values.length + 1);
list.addAll(Arrays.asList(values));
list.add(value);
list.addAll(Arrays.asList(values));
parameterMap.put(name, list.toArray(new String[0]));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public void afterJob(JobExecution jobExecution) {
logger.debug(format("Bulk upload '%s'! %s", jobExecution.getStatus(), jobInfo));
try {
ObjectInfo metadata = bulkUploadS3Service.uploadErrorFile(errorFile, uuid);
logger.debug(format("Bulk upload '%s'! Check for errors at '%s'", jobExecution.getStatus(), metadata.getKey()));
logger.debug(format("Bulk upload '%s'! Check for errors at '%s'. Local file: %s", jobExecution.getStatus(), metadata.getKey(), errorFile.getAbsolutePath()));
} catch (IOException e) {
logger.error(String.format("Unable to create error files in S3 %s", e.getMessage()), e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.collect.Sets;
import org.avni.server.application.FormElement;
import org.avni.server.builder.BuilderException;
import org.avni.server.dao.AddressLevelTypeRepository;
import org.avni.server.dao.LocationRepository;
import org.avni.server.domain.AddressLevel;
Expand All @@ -16,6 +17,7 @@
import org.avni.server.util.CollectionUtil;
import org.avni.server.util.S;
import org.avni.server.web.request.LocationContract;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

Expand All @@ -36,6 +38,7 @@ public class BulkLocationCreator extends BulkLocationModifier {
public static final String ParentMissingOfLocation = "Parent missing for location provided";
public static final String NoLocationProvided = "No location provided";

@Autowired
public BulkLocationCreator(LocationService locationService, LocationRepository locationRepository, AddressLevelTypeRepository addressLevelTypeRepository, ObservationCreator observationCreator, ImportService importService, FormService formService) {
super(locationRepository, observationCreator);
this.locationService = locationService;
Expand Down Expand Up @@ -79,12 +82,12 @@ private List<String> checkIfHeaderHasLocationTypesAndInOrderForHierarchy(String

HashSet<String> expectedHeaders = new HashSet<>(locationTypeNamesForHierarchy);
if (Sets.difference(new HashSet<>(expectedHeaders), new HashSet<>(headerList)).size() == locationTypeNamesForHierarchy.size()) {
allErrorMsgs.add(LocationTypesHeaderError);
allErrorMsgs.add("Location types missing or not in order in header for specified Location Hierarchy. Please refer to sample file for valid list of headers.");
throw new RuntimeException(String.join(", ", allErrorMsgs));
}

if (headerList.size() >= locationTypeNamesForHierarchy.size() && !headerList.subList(0, locationTypeNamesForHierarchy.size()).equals(locationTypeNamesForHierarchy)) {
allErrorMsgs.add(LocationTypesHeaderError);
allErrorMsgs.add("Location types missing or not in order in header for specified Location Hierarchy. Please refer to sample file for valid list of headers.");
throw new RuntimeException(String.join(", ", allErrorMsgs));
}
return locationTypeNamesForHierarchy;
Expand All @@ -97,13 +100,13 @@ private void checkIfHeaderRowHasUnknownHeaders(List<String> additionalHeaders, L
.stream().map(FormElement::getName).collect(Collectors.toList());
locationPropertyNames.add(LocationHeaders.gpsCoordinates);
if ((!locationPropertyNames.containsAll(additionalHeaders))) {
allErrorMsgs.add(UnknownHeadersErrorMessage);
allErrorMsgs.add("Unknown headers included in file. Please refer to sample file for valid list of headers.");
throw new RuntimeException(String.join(", ", allErrorMsgs));
}
}
}

private AddressLevel createAddressLevel(Row row, AddressLevel parent, String header, List<String> locationTypeNames) {
private AddressLevel createAddressLevel(Row row, AddressLevel parent, String header, List<String> locationTypeNames) throws BuilderException {
AddressLevel location;
location = locationRepository.findChildLocation(parent, row.get(header));
if (location == null) {
Expand All @@ -127,11 +130,11 @@ private boolean isValidLocation(String header, Row row, List<String> locationTyp
private void validateRow(Row row, List<String> hierarchicalLocationTypeNames, List<String> allErrorMsgs) {
List<String> values = row.get(hierarchicalLocationTypeNames);
if (CollectionUtil.isEmpty(values)) {
allErrorMsgs.add(NoLocationProvided);
allErrorMsgs.add("No location provided");
throw new RuntimeException(String.join(", ", allErrorMsgs));
}
if (!CollectionUtil.hasOnlyTrailingEmptyStrings(values)) {
allErrorMsgs.add(ParentMissingOfLocation);
allErrorMsgs.add("Parent missing for location provided");
throw new RuntimeException(String.join(", ", allErrorMsgs));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ public void editLocation(Row row, List<String> allErrorMsgs) {

Optional<AddressLevel> existingLocationAddressLevel = locationRepository.findByTitleLineageIgnoreCase(existingLocationTitleLineage);
if (!existingLocationAddressLevel.isPresent()) {
allErrorMsgs.add(String.format("Provided Location does not exist in Avni. Please add it or check for spelling mistakes '%s'", existingLocationTitleLineage));
allErrorMsgs.add(String.format("Provided Location does not exist in Avni. Please add it or check for spelling mistakes and ensure space between two locations '%s'", existingLocationTitleLineage));
throw new RuntimeException(String.join(", ", allErrorMsgs));
}

AddressLevel newLocationParentAddressLevel = null;
if (!StringUtils.isEmpty(newLocationParentTitleLineage)) {
newLocationParentAddressLevel = locationRepository.findByTitleLineageIgnoreCase(newLocationParentTitleLineage).orElse(null);
if (newLocationParentAddressLevel == null) {
allErrorMsgs.add(String.format("Provided new Location parent does not exist in Avni. Please add it or check for spelling mistakes '%s'", newLocationParentTitleLineage));
allErrorMsgs.add(String.format("Provided new location parent does not exist in Avni. Please add it or check for spelling mistakes and ensure space between two locations - '%s'", newLocationParentTitleLineage));
}
}
updateExistingLocation(existingLocationAddressLevel.get(), newLocationParentAddressLevel, row, allErrorMsgs);
Expand Down
Loading

0 comments on commit e9f37b0

Please sign in to comment.