Skip to content

Commit

Permalink
fix: remove Program fk when deleting MapView (#19810)
Browse files Browse the repository at this point in the history
  • Loading branch information
vietnguyen authored Jan 30, 2025
1 parent 90d5014 commit e3bb5d2
Show file tree
Hide file tree
Showing 7 changed files with 359 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,16 @@
import java.util.List;
import org.hisp.dhis.common.AnalyticalObjectStore;
import org.hisp.dhis.organisationunit.OrganisationUnitGroupSet;
import org.hisp.dhis.program.Program;
import org.hisp.dhis.program.ProgramStage;

/**
* @author Morten Olav Hansen <mortenoh@gmail.com>
*/
public interface MapViewStore extends AnalyticalObjectStore<MapView> {
List<MapView> getByOrganisationUnitGroupSet(OrganisationUnitGroupSet groupSet);

List<MapView> findByProgram(Program program);

List<MapView> findByProgramStage(ProgramStage programStage);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import java.util.List;
import org.hisp.dhis.common.AnalyticalObjectService;
import org.hisp.dhis.organisationunit.OrganisationUnitGroupSet;
import org.hisp.dhis.program.Program;
import org.hisp.dhis.program.ProgramStage;

/**
* @author Jan Henrik Overland
Expand Down Expand Up @@ -91,6 +93,10 @@ public interface MappingService extends AnalyticalObjectService<MapView> {

int countMapViewMaps(MapView mapView);

List<MapView> findByProgram(Program program);

List<MapView> findByProgramStage(ProgramStage programStage);

// -------------------------------------------------------------------------
// ExternalMapLayer
// -------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import org.hisp.dhis.period.Period;
import org.hisp.dhis.period.PeriodService;
import org.hisp.dhis.period.RelativePeriods;
import org.hisp.dhis.program.Program;
import org.hisp.dhis.program.ProgramStage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand Down Expand Up @@ -185,6 +187,16 @@ public int countMapViewMaps(MapView mapView) {
return mapStore.countMapViewMaps(mapView);
}

@Override
public List<MapView> findByProgram(Program program) {
return mapViewStore.findByProgram(program);
}

@Override
public List<MapView> findByProgramStage(ProgramStage programStage) {
return mapViewStore.findByProgramStage(programStage);
}

// -------------------------------------------------------------------------
// ExternalMapLayer
// -------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
import org.hisp.dhis.organisationunit.OrganisationUnitGroup;
import org.hisp.dhis.organisationunit.OrganisationUnitGroupSet;
import org.hisp.dhis.period.Period;
import org.hisp.dhis.program.Program;
import org.hisp.dhis.program.ProgramIndicator;
import org.hisp.dhis.program.ProgramStage;
import org.hisp.dhis.system.deletion.DeletionVeto;
import org.springframework.stereotype.Component;

Expand All @@ -67,13 +69,33 @@ protected void registerHandler() {
whenVetoing(Period.class, this::allowDeletePeriod);
whenDeleting(OrganisationUnit.class, this::deleteOrganisationUnit);
whenDeleting(OrganisationUnitGroup.class, this::deleteOrganisationUnitGroup);
whenDeleting(Program.class, this::deleteProgram);
whenDeleting(ProgramStage.class, this::deleteProgramStage);
// special
whenDeleting(LegendSet.class, this::deleteLegendSet);
whenDeleting(OrganisationUnitGroupSet.class, this::deleteOrganisationUnitGroupSetSpecial);
whenDeleting(ExpressionDimensionItem.class, this::deleteExpressionDimensionItem);
whenVetoing(MapView.class, this::allowDeleteMapView);
}

private void deleteProgramStage(ProgramStage programStage) {
List<MapView> mapViews = service.findByProgramStage(programStage);
mapViews.forEach(
mapView -> {
mapView.setProgramStage(null);
service.updateMapView(mapView);
});
}

private void deleteProgram(Program program) {
List<MapView> mapViews = service.findByProgram(program);
mapViews.forEach(
mapView -> {
mapView.setProgram(null);
service.update(mapView);
});
}

private void deleteLegendSet(LegendSet legendSet) {
List<MapView> mapViews = service.getAnalyticalObjects(legendSet);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import org.hisp.dhis.mapping.MapView;
import org.hisp.dhis.mapping.MapViewStore;
import org.hisp.dhis.organisationunit.OrganisationUnitGroupSet;
import org.hisp.dhis.program.Program;
import org.hisp.dhis.program.ProgramStage;
import org.hisp.dhis.security.acl.AclService;
import org.hisp.dhis.user.CurrentUserService;
import org.springframework.context.ApplicationEventPublisher;
Expand Down Expand Up @@ -71,4 +73,23 @@ public List<MapView> getByOrganisationUnitGroupSet(OrganisationUnitGroupSet grou
newJpaParameters()
.addPredicate(root -> builder.equal(root.get("organisationUnitGroupSet"), groupSet)));
}

@Override
public List<MapView> findByProgram(Program program) {
CriteriaBuilder builder = getCriteriaBuilder();

return getList(
builder,
newJpaParameters().addPredicate(root -> builder.equal(root.get("program"), program)));
}

@Override
public List<MapView> findByProgramStage(ProgramStage programStage) {
CriteriaBuilder builder = getCriteriaBuilder();

return getList(
builder,
newJpaParameters()
.addPredicate(root -> builder.equal(root.get("programStage"), programStage)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2004-2025, University of Oslo
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of the HISP project nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hisp.dhis.webapi.controller;

import static org.hisp.dhis.web.WebClientUtils.assertStatus;
import static org.junit.jupiter.api.Assertions.assertFalse;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.hisp.dhis.dataelement.DataElement;
import org.hisp.dhis.jsontree.JsonResponse;
import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
import org.hisp.dhis.web.HttpStatus;
import org.hisp.dhis.webapi.DhisControllerConvenienceTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

class ProgramControllerTest extends DhisControllerConvenienceTest {

@Autowired private ObjectMapper jsonMapper;

public static final String PROGRAM_UID = "PrZMWi7rBga";

@BeforeEach
public void testSetup() throws JsonProcessingException {
DataElement dataElement1 = createDataElement('a');
DataElement dataElement2 = createDataElement('b');
dataElement1.setUid("deabcdefgha");
dataElement2.setUid("deabcdefghb");
TrackedEntityAttribute tea1 = createTrackedEntityAttribute('a');
TrackedEntityAttribute tea2 = createTrackedEntityAttribute('b');
tea1.setUid("TEA1nnnnnaa");
tea2.setUid("TEA1nnnnnab");
POST("/dataElements", jsonMapper.writeValueAsString(dataElement1)).content(HttpStatus.CREATED);
POST("/dataElements", jsonMapper.writeValueAsString(dataElement2)).content(HttpStatus.CREATED);
POST("/trackedEntityAttributes", jsonMapper.writeValueAsString(tea1))
.content(HttpStatus.CREATED);
POST("/trackedEntityAttributes", jsonMapper.writeValueAsString(tea2))
.content(HttpStatus.CREATED);

POST("/metadata", org.hisp.dhis.web.WebClient.Body("program/create_program.json"))
.content(HttpStatus.OK);
}

@Test
void testDeleteWithMapView() {
String mapViewJson =
"{"
+ "\"name\": \"test mapview\","
+ "\"id\": \"mVIVRd23Jm9\","
+ "\"organisationUnitLevels\": [],"
+ "\"maps\": [],"
+ "\"layer\": \"event\","
+ "\"program\": {"
+ "\"id\": \"PrZMWi7rBga\""
+ "},"
+ "\"programStage\": {"
+ "\"id\": \"PSzMWi7rBga\""
+ "}"
+ "}";
POST("/mapViews", mapViewJson).content(HttpStatus.CREATED);
assertStatus(HttpStatus.OK, DELETE(String.format("/programs/%s", PROGRAM_UID)));
assertStatus(HttpStatus.NOT_FOUND, GET(String.format("/programs/%s", PROGRAM_UID)));
JsonResponse mapview = GET("/mapViews/mVIVRd23Jm9").content();
assertFalse(mapview.has("program"));
}
}
Loading

0 comments on commit e3bb5d2

Please # to comment.