Skip to content

Commit

Permalink
fix: Update data dimension items as part of cat opt combo merge [DHIS…
Browse files Browse the repository at this point in the history
…2-18321] (#19687)

* fix: Handle data dimsion items during coc merge [DHIS2-18321]

* fix: Minimise PR change

* fix: clean up
  • Loading branch information
david-mackessy authored Jan 16, 2025
1 parent 73ccf63 commit 4e7da2e
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*/
package org.hisp.dhis.datadimensionitem;

import java.util.Collection;
import java.util.List;
import org.hisp.dhis.common.DataDimensionItem;
import org.hisp.dhis.common.GenericStore;
Expand All @@ -47,4 +48,14 @@ public interface DataDimensionItemStore extends GenericStore<DataDimensionItem>
List<DataDimensionItem> getIndicatorDataDimensionItems(List<Indicator> indicators);

List<DataDimensionItem> getDataElementDataDimensionItems(List<DataElement> dataElements);

/**
* Update the entities with refs to the category option combo ids passed in, with the new category
* option combo id passed in.
*
* @param cocIds category option combo ids to be used to update linked data dimension items
* @param newCocId new category option combo id to use
* @return number of entities updated
*/
int updateDeoCategoryOptionCombo(Collection<Long> cocIds, long newCocId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
package org.hisp.dhis.merge.category.optioncombo;

import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hisp.dhis.category.CategoryCombo;
Expand All @@ -37,6 +38,7 @@
import org.hisp.dhis.category.CategoryOptionStore;
import org.hisp.dhis.common.BaseIdentifiableObject;
import org.hisp.dhis.common.UID;
import org.hisp.dhis.datadimensionitem.DataDimensionItemStore;
import org.hisp.dhis.dataelement.DataElementOperand;
import org.hisp.dhis.dataelement.DataElementOperandStore;
import org.hisp.dhis.minmax.MinMaxDataElement;
Expand All @@ -60,6 +62,7 @@ public class MetadataCategoryOptionComboMergeHandler {
private final CategoryOptionStore categoryOptionStore;
private final CategoryComboStore categoryComboStore;
private final DataElementOperandStore dataElementOperandStore;
private final DataDimensionItemStore dataDimensionItemStore;
private final MinMaxDataElementStore minMaxDataElementStore;
private final PredictorStore predictorStore;
private final SMSCommandStore smsCommandStore;
Expand Down Expand Up @@ -116,6 +119,17 @@ public void handleDataElementOperands(
UID.of(sources.stream().map(BaseIdentifiableObject::getUid).toList()));

dataElementOperands.forEach(deo -> deo.setCategoryOptionCombo(target));

// A data element operand is also a data dimension item.
// The above update does not cascade the reference change though.
// The Data dimension item table also needs updating
int dataDimensionItemsUpdated =
dataDimensionItemStore.updateDeoCategoryOptionCombo(
sources.stream().map(BaseIdentifiableObject::getId).collect(Collectors.toSet()),
target.getId());
log.info(
"{} data dimension items updated as part of category option combo merge",
dataDimensionItemsUpdated);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
package org.hisp.dhis.datadimensionitem.hibernate;

import jakarta.persistence.EntityManager;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.hisp.dhis.common.DataDimensionItem;
import org.hisp.dhis.dataelement.DataElement;
import org.hisp.dhis.hibernate.HibernateGenericStore;
Expand Down Expand Up @@ -69,4 +72,19 @@ public List<DataDimensionItem> getDataElementDataDimensionItems(List<DataElement
.setParameter("dataElements", dataElements)
.getResultList();
}

@Override
public int updateDeoCategoryOptionCombo(@Nonnull Collection<Long> cocIds, long newCocId) {
if (cocIds.isEmpty()) return 0;

String sql =
"""
update datadimensionitem
set dataelementoperand_categoryoptioncomboid = %s
where dataelementoperand_categoryoptioncomboid in (%s)
"""
.formatted(
newCocId, cocIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
return jdbcTemplate.update(sql);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class CategoryOptionComboMergeTest extends ApiTest {
private RestApiActions dataElementApiActions;
private RestApiActions minMaxActions;
private MetadataActions metadataActions;
private RestApiActions visualizationActions;
private RestApiActions maintenanceApiActions;
private RestApiActions dataValueSetActions;
private UserActions userActions;
Expand All @@ -90,6 +91,7 @@ public void before() {
metadataActions = new MetadataActions();
maintenanceApiActions = new RestApiActions("maintenance");
dataValueSetActions = new RestApiActions("dataValueSets");
visualizationActions = new RestApiActions("visualizations");
loginActions.loginAsSuperUser();

// add user with required merge auth
Expand Down Expand Up @@ -145,6 +147,10 @@ void validCategoryOptionComboMergeTest() {
.body("categoryOptions", hasItem(hasEntry("id", "CatOptUid4B")))
.body("categoryOptions", hasItem(hasEntry("id", "CatOptUid3A")));

String dataElement = setupDataElement("test de 1");
// import visualization to persist data dimension item which has ref to source coc
visualizationActions.post(getViz(dataElement, sourceUid1)).validateStatus(201);

// login as merge user
loginActions.loginAsUser("userWithMergeAuth", "Test1234!");

Expand Down Expand Up @@ -410,6 +416,49 @@ private void updateDataValuesAoc() {
.body("response.importCount.updated", equalTo(4));
}

private String getViz(String dataElement, String coc) {
return """

{
"name": "Test viz with data dimension item - DE operand",
"displayName": "Test 1",
"type": "PIVOT_TABLE",
"filters": [
{
"dimension": "ou",
"items": [
{
"id": "USER_ORGUNIT"
}
]
}
],
"columns": [
{
"dimension": "dx",
"items": [
{
"id": "%s.%s",
"dimensionItemType": "DATA_ELEMENT_OPERAND"
}
]
}
],
"rows": [
{
"dimension": "pe",
"items": [
{
"id": "LAST_10_YEARS"
}
]
}
]
}
"""
.formatted(dataElement, coc);
}

private QueryParamsBuilder getDataValueQueryParams() {
return new QueryParamsBuilder()
.add("async=false")
Expand Down Expand Up @@ -494,7 +543,7 @@ void dbConstraintMinMaxTest() {
sourceUid2 = getCocWithOptions("1B", "2B");
targetUid = getCocWithOptions("3A", "4B");

String dataElement = setupDataElement();
String dataElement = setupDataElement("DE test 2");

setupMinMaxDataElements(sourceUid1, sourceUid2, targetUid, dataElement);

Expand All @@ -516,7 +565,7 @@ void dbConstraintMinMaxTest() {
}

private void setupMetadata() {
metadataActions.post(metadata()).validateStatus(200);
metadataActions.importMetadata(metadata()).validateStatus(200);
}

private void setupMinMaxDataElements(
Expand Down Expand Up @@ -546,19 +595,19 @@ private String minMaxDataElements(String coc, String de) {
.formatted(de, coc);
}

private String setupDataElement() {
private String setupDataElement(String name) {
return dataElementApiActions
.post(
"""
{
"aggregationType": "DEFAULT",
"domainType": "AGGREGATE",
"name": "source 19",
"shortName": "source 19",
"displayName": "source 19",
"name": "%s",
"shortName": "%s",
"valueType": "TEXT"
}
""")
"""
.formatted(name, name))
.validateStatus(201)
.extractUid();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,15 +377,13 @@ void dataElementOperandRefsReplacedSourcesDeletedTest() throws ConflictException

List<CategoryOptionCombo> allCOCsAfter = categoryService.getAllCategoryOptionCombos();

assertEquals(7, allCOCsAfter.size(), "7 COCs including 1 default");

// then
assertEquals(7, allCOCsAfter.size(), "7 COCs including 1 default");
assertFalse(report.hasErrorMessages(), "there should be no merge errors");
List<DataElementOperand> deoSourcesAfter =
dataElementOperandStore.getByCategoryOptionCombo(UID.of(cocSource1, cocSource2));
List<DataElementOperand> deoTargetAfter =
dataElementOperandStore.getByCategoryOptionCombo(Set.of(UID.of(cocTarget.getUid())));

assertFalse(report.hasErrorMessages());
assertEquals(
0, deoSourcesAfter.size(), "Expect 0 entries with source category option combo refs");
assertEquals(
Expand Down

0 comments on commit 4e7da2e

Please sign in to comment.