Skip to content

Commit

Permalink
Merge branch 'master' into DHIS2-15957
Browse files Browse the repository at this point in the history
  • Loading branch information
lucaCambi77 authored Oct 26, 2023
2 parents f44b995 + a151ade commit 062f25e
Show file tree
Hide file tree
Showing 276 changed files with 5,411 additions and 1,510 deletions.
57 changes: 57 additions & 0 deletions .github/workflows/deploy-instance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Deploy instance

on:
pull_request:
types: [opened, reopened, labeled, synchronize]

# Cancel previous runs of the same workflow and PR number or branch/tag
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
deploy-instance:
if: contains(github.event.pull_request.labels.*.name, 'deploy')
runs-on: ubuntu-latest
env:
INSTANCE_HOST: 'https://dev.im.dhis2.org'
INSTANCE_NAME: pr-${{ github.event.pull_request.number }}
steps:
- name: Wait for API tests
uses: lewagon/[email protected]
with:
ref: ${{ github.head_ref }}
check-name: 'api-test'
repo-token: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/checkout@v4
with:
repository: dhis2-sre/im-manager
sparse-checkout: scripts/instances

- name: Install HTTPie
run: python -m pip install httpie

- name: Deploy DHIS2 instance
working-directory: scripts/instances
env:
HTTP: https --check-status
USER_EMAIL: ${{ secrets.IM_BOT_EMAIL }}
PASSWORD: ${{ secrets.IM_BOT_PASSWORD }}
IM_HOST: 'https://api.im.dhis2.org'
IMAGE_REPOSITORY: core-pr
IMAGE_TAG: ${{ github.event.pull_request.number }}
IMAGE_PULL_POLICY: Always
DATABASE_ID: sl-sierra-leone-dev-sql-gz
run: ./findByName.sh dev $INSTANCE_NAME && ./restart.sh dev $INSTANCE_NAME || ./deploy-dhis2.sh dev $INSTANCE_NAME

- name: Wait for instance
run: timeout 300 bash -c 'while [[ "$(curl -fsSL -o /dev/null -w %{http_code} $INSTANCE_HOST/$INSTANCE_NAME)" != "200" ]]; do sleep 5; done'

- name: Generate analytics
run: curl -X POST -u "${{ secrets.DHIS2_USERNAME }}:${{ secrets.DHIS2_PASSWORD }}" "$INSTANCE_HOST/$INSTANCE_NAME/api/resourceTables/analytics" -d 'executeTei=true'

- name: Comment instance URL
uses: actions-cool/maintain-one-comment@v3
with:
body: "Instance deployed to https://dev.im.dhis2.org/pr-${{ github.event.pull_request.number }}"
32 changes: 32 additions & 0 deletions .github/workflows/destroy-instance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Destroy instance

on:
pull_request:
types: [closed]

# Cancel previous runs of the same workflow and PR number or branch/tag
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
destroy-instance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
repository: dhis2-sre/im-manager
sparse-checkout: scripts/instances

- name: Install HTTPie
run: python -m pip install httpie

- name: Destroy DHIS2 instance
working-directory: scripts/instances
env:
HTTP: https --check-status
USER_EMAIL: ${{ secrets.IM_BOT_EMAIL }}
PASSWORD: ${{ secrets.IM_BOT_PASSWORD }}
IM_HOST: 'https://api.im.dhis2.org'
INSTANCE_NAME: pr-${{ github.event.number }}
run: ./findByName.sh dev $INSTANCE_NAME && ./destroy.sh dev $INSTANCE_NAME
4 changes: 2 additions & 2 deletions .github/workflows/run-api-analytics-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ concurrency:
group: ${{ github.workflow}}-${{ github.ref }}
cancel-in-progress: true
jobs:
api-test:
api-analytics-test:
env:
CORE_IMAGE_NAME: "dhis2/core-dev:local"
PR_NUMBER: ${{ github.event.number }}
Expand Down Expand Up @@ -88,7 +88,7 @@ jobs:
contains(needs.*.result, 'failure') &&
github.ref == 'refs/heads/master'
needs: [ api-test ]
needs: [ api-analytics-test ]
steps:
- uses: rtCamp/action-slack-notify@v2
env:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,6 @@ public enum AggregationType {
private static final EnumSet<AggregationType> FIRST_TYPES =
EnumSet.of(FIRST, FIRST_AVERAGE_ORG_UNIT, FIRST_FIRST_ORG_UNIT);

/**
* Types that allow non-numeric output such as String or boolean (and possibly also numeric
* output)
*/
private static final EnumSet<AggregationType> ALLOWS_NONNUMERIC_TYPES =
EnumSet.of(LAST, FIRST, MIN, MAX, NONE, CUSTOM, DEFAULT);

private final String value;

private boolean aggregatable;
Expand Down Expand Up @@ -99,10 +92,6 @@ public boolean isFirst() {
return FIRST_TYPES.contains(this);
}

public boolean allowsNonnumeric() {
return ALLOWS_NONNUMERIC_TYPES.contains(this);
}

public static AggregationType fromValue(String value) {
for (AggregationType type : AggregationType.values()) {
if (type.value.equalsIgnoreCase(value)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,16 @@ public enum AnalyticsMetaDataKey {
ITEMS("items"),
DIMENSIONS("dimensions"),
PAGER("pager"),
ORG_UNITS("organisationUnits"),
ORG_UNIT_HIERARCHY("ouHierarchy"),
ORG_UNIT_NAME_HIERARCHY("ouNameHierarchy"),
ORG_UNIT_ANCESTORS("ouAncestors");
ORG_UNIT_ANCESTORS("ouAncestors"),
USER_ORGUNIT("USER_ORGUNIT"),

private String key;
USER_ORGUNIT_CHILDREN("USER_ORGUNIT_CHILDREN"),
USER_ORGUNIT_GRANDCHILDREN("USER_ORGUNIT_GRANDCHILDREN");

private final String key;

AnalyticsMetaDataKey(String key) {
this.key = key;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
import static org.hisp.dhis.common.DimensionalObject.ORGUNIT_DIM_ID;
import static org.hisp.dhis.common.DimensionalObject.PERIOD_DIM_ID;
import static org.hisp.dhis.common.DimensionalObject.STATIC_DIMS;
import static org.hisp.dhis.common.DimensionalObjectUtils.asActualDimension;
import static org.hisp.dhis.common.DimensionalObjectUtils.linkAssociations;
import static org.hisp.dhis.common.DxfNamespaces.DXF_2_0;
import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_LEVEL;
import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_ORGUNIT_GROUP;
Expand Down Expand Up @@ -79,7 +81,6 @@
import org.hisp.dhis.dataelement.DataElement;
import org.hisp.dhis.dataelement.DataElementGroupSetDimension;
import org.hisp.dhis.eventvisualization.Attribute;
import org.hisp.dhis.eventvisualization.EventRepetition;
import org.hisp.dhis.eventvisualization.SimpleDimension;
import org.hisp.dhis.eventvisualization.SimpleDimension.Type;
import org.hisp.dhis.eventvisualization.SimpleDimensionHandler;
Expand Down Expand Up @@ -587,18 +588,20 @@ protected DimensionalObject getDimensionalObject(
* (one that is not defined anywhere and only exists for very specific use cases. See {@link
* SimpleDimension}).
*
* @param eventAnalyticalObject the object of type EventAnalyticalObject
* @param dimension the dimension, ie: dx, pe, eventDate
* @param eventAnalyticalObject the object of type {@link EventAnalyticalObject}.
* @param dimension the dimension, ie: dx, pe, eventDate. It can be a qualified one like
* program.eventDate, or program.stage.dimension.
* @param parent the parent attribute
* @return the dimensional object related to the given dimension and attribute.
*/
protected DimensionalObject getDimensionalObject(
EventAnalyticalObject eventAnalyticalObject, String dimension, Attribute parent) {
Optional<DimensionalObject> optionalDimensionalObject = getDimensionalObject(dimension);
String actualDim = asActualDimension(dimension);

if (optionalDimensionalObject.isPresent()) {
return linkAssociations(eventAnalyticalObject, optionalDimensionalObject.get(), parent);
} else if (Type.contains(dimension)) {
} else if (Type.contains(actualDim)) {
DimensionalObject dimensionalObject =
new SimpleDimensionHandler(eventAnalyticalObject).getDimensionalObject(dimension, parent);

Expand All @@ -608,35 +611,6 @@ protected DimensionalObject getDimensionalObject(
}
}

/**
* This method links existing associations between objects. This is mainly needed in cases where
* attributes need to be programmatically associated to fulfill client requirements.
*
* @param eventAnalyticalObject the source object
* @param dimensionalObject where the associations will happen
* @param parent the parent attribute, where the association object should be appended to
* @return the dimensional object containing the correct associations.
*/
private DimensionalObject linkAssociations(
EventAnalyticalObject eventAnalyticalObject,
DimensionalObject dimensionalObject,
Attribute parent) {
// Associating event repetitions.
List<EventRepetition> repetitions = eventAnalyticalObject.getEventRepetitions();

if (isNotEmpty(repetitions)) {
for (EventRepetition eventRepetition : repetitions) {
if (eventRepetition.getDimension() != null
&& eventRepetition.getDimension().equals(dimensionalObject.getDimension())
&& parent == eventRepetition.getParent()) {
((BaseDimensionalObject) dimensionalObject).setEventRepetition(eventRepetition);
}
}
}

return dimensionalObject;
}

/**
* Populates the given dimensionalObjects list based on the respective dimensions provided.
*
Expand Down Expand Up @@ -693,11 +667,13 @@ protected void populateDimensions(
* @return a list of DimensionalObjects.
*/
protected Optional<DimensionalObject> getDimensionalObject(String dimension) {
if (DATA_X_DIM_ID.equals(dimension)) {
String actualDim = asActualDimension(dimension);

if (DATA_X_DIM_ID.equals(actualDim)) {
return Optional.of(
new BaseDimensionalObject(
dimension, DimensionType.DATA_X, getDataDimensionNameableObjects()));
} else if (PERIOD_DIM_ID.equals(dimension)) {
} else if (PERIOD_DIM_ID.equals(actualDim)) {
List<Period> periodList = new ArrayList<>(periods);

if (hasRelativePeriods()) {
Expand All @@ -709,7 +685,7 @@ protected Optional<DimensionalObject> getDimensionalObject(String dimension) {
}

return Optional.of(new BaseDimensionalObject(dimension, DimensionType.PERIOD, periodList));
} else if (ORGUNIT_DIM_ID.equals(dimension)) {
} else if (ORGUNIT_DIM_ID.equals(actualDim)) {
List<DimensionalItemObject> ouList = new ArrayList<>();
ouList.addAll(organisationUnits);
ouList.addAll(transientOrganisationUnits);
Expand Down Expand Up @@ -744,14 +720,14 @@ protected Optional<DimensionalObject> getDimensionalObject(String dimension) {

return Optional.of(
new BaseDimensionalObject(dimension, DimensionType.ORGANISATION_UNIT, ouList));
} else if (CATEGORYOPTIONCOMBO_DIM_ID.equals(dimension)) {
} else if (CATEGORYOPTIONCOMBO_DIM_ID.equals(actualDim)) {
return Optional.of(
new BaseDimensionalObject(
dimension, DimensionType.CATEGORY_OPTION_COMBO, new ArrayList<>()));
} else if (DATA_COLLAPSED_DIM_ID.equals(dimension)) {
} else if (DATA_COLLAPSED_DIM_ID.equals(actualDim)) {
return Optional.of(
new BaseDimensionalObject(dimension, DimensionType.DATA_COLLAPSED, new ArrayList<>()));
} else if (STATIC_DIMS.contains(dimension)) {
} else if (STATIC_DIMS.contains(actualDim)) {
return Optional.of(
new BaseDimensionalObject(dimension, DimensionType.STATIC, new ArrayList<>()));
} else {
Expand Down Expand Up @@ -788,13 +764,15 @@ private Optional<DimensionalObject> getDimensionFromEmbeddedObjects(String dimen
}

private Optional<DimensionalObject> getTrackedEntityDimension(String dimension) {
String actualDim = asActualDimension(dimension);

// Tracked entity attribute.
Map<String, TrackedEntityAttributeDimension> attributes =
attributeDimensions.stream()
.collect(toMap(TrackedEntityAttributeDimension::getUid, Function.identity()));

if (attributes.containsKey(dimension)) {
TrackedEntityAttributeDimension tead = attributes.get(dimension);
if (attributes.containsKey(actualDim)) {
TrackedEntityAttributeDimension tead = attributes.get(actualDim);

if (tead != null) {
ValueType valueType =
Expand All @@ -819,15 +797,15 @@ private Optional<DimensionalObject> getTrackedEntityDimension(String dimension)

// Tracked entity data element.
for (TrackedEntityDataElementDimension tedd : dataElementDimensions) {
if (tedd != null && dimension.equals(tedd.getUid())) {
if (tedd != null && actualDim.equals(tedd.getUid())) {
ValueType valueType =
tedd.getDataElement() != null ? tedd.getDataElement().getValueType() : null;

OptionSet optionSet =
tedd.getDataElement() != null ? tedd.getDataElement().getOptionSet() : null;

String elementProgramStage =
dimension + (tedd.getProgramStage() != null ? tedd.getProgramStage().getUid() : EMPTY);
actualDim + (tedd.getProgramStage() != null ? tedd.getProgramStage().getUid() : EMPTY);

// Return dimensions with distinct program stages.
if (!addedElementsProgramStages.contains(elementProgramStage)) {
Expand All @@ -854,8 +832,8 @@ private Optional<DimensionalObject> getTrackedEntityDimension(String dimension)
programIndicatorDimensions.stream()
.collect(toMap(TrackedEntityProgramIndicatorDimension::getUid, Function.identity()));

if (programIndicators.containsKey(dimension)) {
TrackedEntityProgramIndicatorDimension teid = programIndicators.get(dimension);
if (programIndicators.containsKey(actualDim)) {
TrackedEntityProgramIndicatorDimension teid = programIndicators.get(actualDim);

return Optional.of(
new BaseDimensionalObject(
Expand Down Expand Up @@ -883,11 +861,13 @@ private Optional<DimensionalObject> getTrackedEntityDimension(String dimension)
private <T extends DimensionalEmbeddedObject>
Optional<DimensionalObject> getDimensionFromEmbeddedObjects(
String dimension, DimensionType dimensionType, List<T> embeddedObjects) {
String actualDim = asActualDimension(dimension);

Map<String, T> dimensions =
Maps.uniqueIndex(embeddedObjects, d -> d.getDimension().getDimension());

if (dimensions.containsKey(dimension)) {
DimensionalEmbeddedObject object = dimensions.get(dimension);
if (dimensions.containsKey(actualDim)) {
DimensionalEmbeddedObject object = dimensions.get(actualDim);

if (object != null) {
return Optional.of(
Expand Down
Loading

0 comments on commit 062f25e

Please sign in to comment.