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

chore: get one trackedEntity via path and query param is identical DHIS2-18541 #19377

Closed
wants to merge 4 commits into from
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
import org.hisp.dhis.trackedentity.TrackedEntityAttributeService;
import org.hisp.dhis.trackedentity.TrackedEntityAudit;
import org.hisp.dhis.trackedentity.TrackedEntityProgramOwner;
import org.hisp.dhis.trackedentity.TrackedEntityType;
import org.hisp.dhis.trackedentity.TrackedEntityTypeService;
import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue;
Expand Down Expand Up @@ -217,83 +216,30 @@ public TrackedEntity getTrackedEntity(@Nonnull UID uid)
UserDetails currentUser = getCurrentUserDetails();
TrackedEntity trackedEntity =
mapTrackedEntity(
getTrackedEntity(uid, currentUser),
TrackedEntityParams.FALSE,
currentUser,
null,
false);
getTrackedEntity(uid, currentUser), TrackedEntityParams.FALSE, currentUser, false);
mapTrackedEntityTypeAttributes(trackedEntity);
return trackedEntity;
}

@Override
public TrackedEntity getTrackedEntity(
@Nonnull UID trackedEntityUid,
@CheckForNull UID programIdentifier,
@Nonnull TrackedEntityParams params)
throws NotFoundException, ForbiddenException {
Program program = null;

if (programIdentifier != null) {
program = programService.getProgram(programIdentifier.getValue());
if (program == null) {
throw new NotFoundException(Program.class, programIdentifier);
}
}

TrackedEntity trackedEntity;
if (program != null) {
trackedEntity = getTrackedEntity(trackedEntityUid.getValue(), program, params);

if (params.isIncludeProgramOwners()) {
Set<TrackedEntityProgramOwner> filteredProgramOwners =
trackedEntity.getProgramOwners().stream()
.filter(te -> te.getProgram().getUid().equals(programIdentifier.getValue()))
.collect(Collectors.toSet());
trackedEntity.setProgramOwners(filteredProgramOwners);
}
} else {
UserDetails userDetails = getCurrentUserDetails();

trackedEntity =
mapTrackedEntity(
getTrackedEntity(trackedEntityUid, userDetails), params, userDetails, null, false);

mapTrackedEntityTypeAttributes(trackedEntity);
}
return trackedEntity;
}

/**
* Gets a tracked entity based on the program and org unit ownership
*
* @return the TE object if found and accessible by the current user
* @throws NotFoundException if uid does not exist
* @throws ForbiddenException if TE owner is not in user's scope or not enough sharing access
*/
private TrackedEntity getTrackedEntity(String uid, Program program, TrackedEntityParams params)
throws NotFoundException, ForbiddenException {
TrackedEntity trackedEntity = trackedEntityStore.getByUid(uid);
trackedEntityAuditService.addTrackedEntityAudit(trackedEntity, getCurrentUsername(), READ);
if (trackedEntity == null) {
throw new NotFoundException(TrackedEntity.class, uid);
}
@Nonnull UID trackedEntity, @CheckForNull UID program, @Nonnull TrackedEntityParams params)
throws NotFoundException, ForbiddenException, BadRequestException {
Page<TrackedEntity> trackedEntities;

UserDetails userDetails = getCurrentUserDetails();
List<String> errors =
trackerAccessManager.canReadProgramAndTrackedEntityType(
userDetails, trackedEntity, program);
if (!errors.isEmpty()) {
throw new ForbiddenException(errors.toString());
}
TrackedEntityOperationParams operationParams =
TrackedEntityOperationParams.builder()
.trackedEntities(Set.of(trackedEntity))
.program(program)
.trackedEntityParams(params)
.build();
trackedEntities = getTrackedEntities(operationParams, new PageParams(1, 1, false));

String error =
trackerAccessManager.canAccessProgramOwner(userDetails, trackedEntity, program, false);
if (error != null) {
throw new ForbiddenException(error);
if (trackedEntities.getItems().isEmpty()) {
throw new NotFoundException(TrackedEntity.class, trackedEntity.getValue());
}

return mapTrackedEntity(trackedEntity, params, userDetails, program, false);
return trackedEntities.getItems().get(0);
}

/**
Expand Down Expand Up @@ -338,7 +284,6 @@ private TrackedEntity mapTrackedEntity(
TrackedEntity trackedEntity,
TrackedEntityParams params,
UserDetails user,
Program program,
boolean includeDeleted) {
TrackedEntity result = new TrackedEntity();
result.setId(trackedEntity.getId());
Expand All @@ -361,13 +306,13 @@ private TrackedEntity mapTrackedEntity(
result.setRelationshipItems(getRelationshipItems(trackedEntity, user, includeDeleted));
}
if (params.isIncludeEnrollments()) {
result.setEnrollments(getEnrollments(trackedEntity, user, includeDeleted, program));
result.setEnrollments(getEnrollments(trackedEntity, user, includeDeleted));
}
if (params.isIncludeProgramOwners()) {
result.setProgramOwners(trackedEntity.getProgramOwners());
}

result.setTrackedEntityAttributeValues(getTrackedEntityAttributeValues(trackedEntity, program));
result.setTrackedEntityAttributeValues(getTrackedEntityAttributeValues(trackedEntity));

return result;
}
Expand All @@ -388,9 +333,8 @@ private Set<RelationshipItem> getRelationshipItems(
}

private Set<Enrollment> getEnrollments(
TrackedEntity trackedEntity, UserDetails user, boolean includeDeleted, Program program) {
TrackedEntity trackedEntity, UserDetails user, boolean includeDeleted) {
return trackedEntity.getEnrollments().stream()
.filter(e -> program == null || program.getUid().equals(e.getProgram().getUid()))
.filter(e -> includeDeleted || !e.isDeleted())
.filter(e -> trackerAccessManager.canRead(user, e, false).isEmpty())
.map(
Expand All @@ -409,19 +353,12 @@ private Set<Enrollment> getEnrollments(
}

private Set<TrackedEntityAttributeValue> getTrackedEntityAttributeValues(
TrackedEntity trackedEntity, Program program) {
TrackedEntity trackedEntity) {
Set<String> readableAttributes =
trackedEntity.getTrackedEntityType().getTrackedEntityAttributes().stream()
.map(IdentifiableObject::getUid)
.collect(Collectors.toSet());

if (program != null) {
readableAttributes.addAll(
program.getTrackedEntityAttributes().stream()
.map(IdentifiableObject::getUid)
.collect(Collectors.toSet()));
}

return trackedEntity.getTrackedEntityAttributeValues().stream()
.filter(av -> readableAttributes.contains(av.getAttribute().getUid()))
.collect(Collectors.toSet());
Expand Down Expand Up @@ -484,10 +421,11 @@ private RelationshipItem getTrackedEntityInRelationshipItem(
}

relationshipItem.setTrackedEntity(
mapTrackedEntity(trackedEntity, params, currentUser, null, includeDeleted));
mapTrackedEntity(trackedEntity, params, currentUser, includeDeleted));
return relationshipItem;
}

@Nonnull
@Override
public List<TrackedEntity> getTrackedEntities(
@Nonnull TrackedEntityOperationParams operationParams)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,8 @@ private String getCountQueryWithMaxTrackedEntityLimit(TrackedEntityQueryParams p
+ getQuerySelect(params)
+ "FROM "
+ getFromSubQuery(params, true, null)
+ (params.getProgram().getMaxTeiCountToReturn() > 0
? getLimitClause(params.getProgram().getMaxTeiCountToReturn() + 1)
+ (params.getEnrolledInTrackerProgram().getMaxTeiCountToReturn() > 0
? getLimitClause(params.getEnrolledInTrackerProgram().getMaxTeiCountToReturn() + 1)
: "")
+ " ) tecount";
}
Expand Down Expand Up @@ -448,7 +448,7 @@ private String joinPrograms(TrackedEntityQueryParams params) {
if (!params.hasProgram()) {
trackedEntity
.append("AND P.programid IN (")
.append(getCommaDelimitedString(getIdentifiers(params.getPrograms())))
.append(getCommaDelimitedString(getIdentifiers(params.getAccessibleTrackerPrograms())))
.append(")");
}

Expand Down Expand Up @@ -594,23 +594,23 @@ private String getFromSubQueryJoinOrderByAttributes(TrackedEntityQueryParams par
}

/**
* Generates an INNER JOIN for program owner. This segment is only included if program is
* specified.
* Generates an INNER JOIN for program owner.
*
* @return a SQL INNER JOIN for program owner, or a LEFT JOIN if no program is specified.
*/
private String getFromSubQueryJoinProgramOwnerConditions(TrackedEntityQueryParams params) {
if (params.hasProgram()) {
return " INNER JOIN trackedentityprogramowner PO "
+ " ON PO.programid = "
+ params.getProgram().getId()
+ params.getEnrolledInTrackerProgram().getId()
+ " AND PO.trackedentityid = TE.trackedentityid "
+ " AND P.programid = PO.programid";
}

return "LEFT JOIN trackedentityprogramowner PO ON "
+ " PO.trackedentityid = TE.trackedentityid"
+ " AND P.programid = PO.programid";
return """
LEFT JOIN trackedentityprogramowner PO ON \
PO.trackedentityid = TE.trackedentityid\
AND P.programid = PO.programid""";
}

/**
Expand Down Expand Up @@ -738,14 +738,14 @@ private String getFromSubQueryJoinEnrollmentConditions(TrackedEntityQueryParams

String join =
"""
INNER JOIN enrollment %1$s
ON %1$s.trackedentityid = TE.trackedentityid
""";
INNER JOIN enrollment %1$s
ON %1$s.trackedentityid = TE.trackedentityid
""";

return !params.hasProgram()
? join.formatted(ENROLLMENT_ALIAS)
: join.concat(" AND %1$s.programid = %2$s")
.formatted(ENROLLMENT_ALIAS, params.getProgram().getId());
.formatted(ENROLLMENT_ALIAS, params.getEnrolledInTrackerProgram().getId());
}

return "";
Expand Down Expand Up @@ -780,7 +780,7 @@ private String getFromSubQueryEnrollmentConditions(
program
.append("WHERE EN.trackedentityid = TE.trackedentityid ")
.append("AND EN.programid = ")
.append(params.getProgram().getId())
.append(params.getEnrolledInTrackerProgram().getId())
.append(SPACE);

if (params.hasEnrollmentStatus()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ public class TrackedEntityOperationParams {
/** Tracked entity type to fetch. */
private UID trackedEntityType;

private OrganisationUnitSelectionMode orgUnitMode;
@Builder.Default
private OrganisationUnitSelectionMode orgUnitMode = OrganisationUnitSelectionMode.ACCESSIBLE;

@Getter @Builder.Default
private AssignedUserQueryParam assignedUserQueryParam = AssignedUserQueryParam.ALL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public TrackedEntityQueryParams map(

List<TrackedEntityType> trackedEntityTypes = getTrackedEntityTypes(program, user);

List<Program> programs = getTrackerPrograms(program, user);
List<Program> accessibleTrackerPrograms = getAccessibleTrackerPrograms(program, user);

Set<OrganisationUnit> orgUnits =
paramsValidator.validateOrgUnits(operationParams.getOrganisationUnits(), user);
Expand All @@ -114,8 +114,8 @@ public TrackedEntityQueryParams map(
program, requestedTrackedEntityType, operationParams, orgUnits, params);

params
.setProgram(program)
.setPrograms(programs)
.setEnrolledInTrackerProgram(program)
.setAccessibleTrackerPrograms(accessibleTrackerPrograms)
.setProgramStage(programStage)
.setEnrollmentStatus(operationParams.getEnrollmentStatus())
.setFollowUp(operationParams.getFollowUp())
Expand Down Expand Up @@ -167,7 +167,7 @@ private List<TrackedEntityType> filterAndValidateTrackedEntityTypes(UserDetails
return trackedEntityTypes;
}

private List<Program> getTrackerPrograms(Program program, UserDetails user) {
private List<Program> getAccessibleTrackerPrograms(Program program, UserDetails user) {
if (program == null) {
return programService.getAllPrograms().stream()
.filter(Program::isRegistration)
Expand Down Expand Up @@ -242,7 +242,8 @@ private void mapOrderParam(TrackedEntityQueryParams params, List<Order> orders)
throw new BadRequestException(
"Cannot order by '"
+ uid.getValue()
+ "' as its not a tracked entity attribute. Tracked entities can be ordered by fields and tracked entity attributes.");
+ "' as its not a tracked entity attribute. Tracked entities can be ordered by"
+ " fields and tracked entity attributes.");
}

params.orderBy(tea, order.getDirection());
Expand Down Expand Up @@ -298,7 +299,8 @@ private List<UID> getSearchableAttributeIds(TrackedEntityQueryParams params) {
List<UID> searchableAttributeIds = new ArrayList<>();

if (params.hasProgram()) {
searchableAttributeIds.addAll(UID.of(params.getProgram().getSearchableAttributeIds()));
searchableAttributeIds.addAll(
UID.of(params.getEnrolledInTrackerProgram().getSearchableAttributeIds()));
}

if (params.hasTrackedEntityType()) {
Expand Down Expand Up @@ -347,12 +349,12 @@ private int getMaxTeiLimit(TrackedEntityQueryParams params) {
}

if (params.hasProgram()) {
maxTeiLimit = params.getProgram().getMaxTeiCountToReturn();
maxTeiLimit = params.getEnrolledInTrackerProgram().getMaxTeiCountToReturn();

if (!params.hasTrackedEntities() && isProgramMinAttributesViolated(params)) {
throw new IllegalQueryException(
"At least "
+ params.getProgram().getMinAttributesRequiredToSearch()
+ params.getEnrolledInTrackerProgram().getMinAttributesRequiredToSearch()
+ " attributes should be mentioned in the search criteria.");
}
}
Expand Down Expand Up @@ -405,9 +407,11 @@ private boolean isProgramMinAttributesViolated(TrackedEntityQueryParams params)
return false;
}

return (!params.hasFilters() && params.getProgram().getMinAttributesRequiredToSearch() > 0)
return (!params.hasFilters()
&& params.getEnrolledInTrackerProgram().getMinAttributesRequiredToSearch() > 0)
|| (params.hasFilters()
&& params.getFilters().size() < params.getProgram().getMinAttributesRequiredToSearch());
&& params.getFilters().size()
< params.getEnrolledInTrackerProgram().getMinAttributesRequiredToSearch());
}

private void checkIfMaxTeiLimitIsReached(TrackedEntityQueryParams params, int maxTeiLimit) {
Expand Down
Loading
Loading