Skip to content
Open
1,235 changes: 1,098 additions & 137 deletions amp/TEMPLATE/reamp/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion amp/TEMPLATE/reamp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"author": "Alexei Savca",
"license": "inherit",
"devDependencies": {
"amp-ui": "github:devgateway/amp-ui#develop",
"amp-ui": "github:devgateway/amp-ui#add-missing-me-fields-to-preview-and-api",
"babel-core": "^6.26.3",
"babel-jest": "^6.0.1",
"babel-loader": "^6.3.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,9 +305,108 @@ private static void addExtraFieldsToActivity(Map<String, Object> activityFields,
.findFirst();

addActualIndicatorValues(indicatorsObject, projectId);
addDisaggregationValues(indicatorsObject);
resolveIndicatorActivityLocations(indicatorsObject);
}
}

/**
* Replaces each indicator's {@code activity_location} value (an AmpActivityLocation PK)
* with the inner AmpCategoryValueLocations id so the frontend can hydrate it to a location name
* via the standard locations id-values pipeline
*/
private static void resolveIndicatorActivityLocations(Optional<Object> indicatorsObject) {
indicatorsObject.ifPresent(indicators -> {
if (!(indicators instanceof ArrayList)) {
return;
}
List<Map<String, Object>> indicatorsList = (ArrayList<Map<String, Object>>) indicators;
for (Map<String, Object> indicator : indicatorsList) {
Object rawLocId = indicator.get("activity_location");
if (rawLocId == null) {
continue;
}
Long ampActivityLocationId = (rawLocId instanceof Long)
? (Long) rawLocId : Long.valueOf(rawLocId.toString());
try {
AmpActivityLocation aal = (AmpActivityLocation)
PersistenceManager.getSession().get(AmpActivityLocation.class, ampActivityLocationId);
if (aal != null && aal.getLocation() != null) {
indicator.put("activity_location", aal.getLocation().getId());
}
} catch (Exception e) {
logger.error("Failed to resolve AmpActivityLocation id=" + ampActivityLocationId
+ " to inner location", e);
}
}
});
}

private static void addDisaggregationValues(Optional<Object> indicatorsObject) {
indicatorsObject.ifPresent(indicators -> {
if (indicators instanceof ArrayList) {
List<Map<String, Object>> indicatorsList = (ArrayList<Map<String, Object>>) indicators;
for (Map<String, Object> indicator : indicatorsList) {
Long indicatorId = (Long) indicator.get("indicator");
if (indicatorId == null) {
continue;
}
AmpIndicator ampIndicator;
try {
ampIndicator = IndicatorUtil.getIndicator(indicatorId);
} catch (DgException e) {
logger.error("Failed to load AmpIndicator id=" + indicatorId + " for disaggregation values", e);
continue;
}
if (ampIndicator == null || ampIndicator.getDisaggregationValues() == null) {
indicator.put("disaggregation_values", Collections.emptyList());
continue;
}
List<Map<String, Object>> disaggList = new ArrayList<>();
for (AmpIndicatorDisaggregationValue dv : ampIndicator.getDisaggregationValues()) {
Map<String, Object> dvMap = new LinkedHashMap<>();
dvMap.put("id", dv.getId());
dvMap.put("parent_category",
dv.getParentCategory() != null ? dv.getParentCategory().getId() : null);
dvMap.put("parent_category_name",
dv.getParentCategory() != null ? dv.getParentCategory().getValue() : null);
dvMap.put("child_category",
dv.getChildCategory() != null ? dv.getChildCategory().getId() : null);
dvMap.put("child_category_name",
dv.getChildCategory() != null ? dv.getChildCategory().getValue() : null);
dvMap.put("base_value", serializeGlobalValue(dv.getBaseValue()));
dvMap.put("target_value", serializeGlobalValue(dv.getTargetValue()));
List<Map<String, Object>> actualValues = new ArrayList<>();
if (dv.getActualValues() != null) {
for (AmpIndicatorGlobalValue av : dv.getActualValues()) {
actualValues.add(serializeGlobalValue(av));
}
}
dvMap.put("actual_values", actualValues);
disaggList.add(dvMap);
}
indicator.put("disaggregation_values", disaggList);
}
}
});
}

private static Map<String, Object> serializeGlobalValue(AmpIndicatorGlobalValue gv) {
if (gv == null) {
return null;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Map<String, Object> map = new LinkedHashMap<>();
map.put("id", gv.getId());
map.put("original_value", gv.getOriginalValue());
map.put("original_value_date",
gv.getOriginalValueDate() != null ? dateFormat.format(gv.getOriginalValueDate()) : null);
map.put("revised_value", gv.getRevisedValue());
map.put("revised_value_date",
gv.getRevisedValueDate() != null ? dateFormat.format(gv.getRevisedValueDate()) : null);
return map;
}

private static void addActualIndicatorValues(Optional<Object> indicatorsObject, Long projectId){
// Loop through the elements of the ArrayList if present in indicators
indicatorsObject.ifPresent(indicators -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.digijava.kernel.validators.common.RequiredValidator;
import org.digijava.module.aim.annotations.interchange.*;
import org.digijava.module.aim.util.AmpAutoCompleteDisplayable;
import org.digijava.module.aim.util.Identifiable;
import org.digijava.module.aim.util.Output;
import org.digijava.module.aim.util.TreeNodeAware;
import org.jetbrains.annotations.NotNull;
Expand All @@ -20,7 +21,7 @@
*
*/
public class AmpActivityLocation implements Comparable<AmpActivityLocation>, Versionable, Serializable, Cloneable,
TreeNodeAware<AmpCategoryValueLocations> {
TreeNodeAware<AmpCategoryValueLocations>, Identifiable {

//IATI-check: should be exported.
@InterchangeableId
Expand Down Expand Up @@ -58,6 +59,11 @@ public Long getId() {
public void setId(Long id) {
this.id = id;
}

@Override
public Object getIdentifier() {
return id;
}
public AmpActivityVersion getActivity() {
return activity;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
package org.digijava.module.aim.dbentity;

import org.digijava.module.aim.annotations.interchange.Interchangeable;
import org.digijava.module.aim.annotations.interchange.InterchangeableBackReference;
import org.digijava.module.aim.annotations.interchange.InterchangeableId;
import org.digijava.module.categorymanager.dbentity.AmpCategoryValue;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.io.Serializable;
import java.util.Set;
import java.util.HashSet;

public class AmpIndicatorDisaggregationValue implements Serializable {
@InterchangeableId
@Interchangeable(fieldTitle = "Id")
private Long id;

@Interchangeable(fieldTitle = "Parent Category", importable = true, pickIdOnly = true)
private AmpCategoryValue parentCategory;

@Interchangeable(fieldTitle = "Child Category", importable = true, pickIdOnly = true)
private AmpCategoryValue childCategory;

@Interchangeable(fieldTitle = "Base Value", importable = true)
private AmpIndicatorGlobalValue baseValue;

@Interchangeable(fieldTitle = "Target Value", importable = true)
private AmpIndicatorGlobalValue targetValue;

// changed from List to Set and will be mapped via hbm
@Interchangeable(fieldTitle = "Actual Values", importable = true)
private Set<AmpIndicatorGlobalValue> actualValues; // @OneToMany like mapping in hbm (inverse)

@InterchangeableBackReference
private AmpIndicator indicator;

public AmpIndicatorGlobalValue getBaseValue() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import io.swagger.annotations.ApiModelProperty;
import org.digijava.kernel.ampapi.endpoints.serializers.LocalizedDateDeserializer;
import org.digijava.kernel.ampapi.endpoints.serializers.LocalizedDateSerializer;
import org.digijava.module.aim.annotations.interchange.Interchangeable;
import org.digijava.module.aim.annotations.interchange.InterchangeableBackReference;
import org.digijava.module.aim.annotations.interchange.InterchangeableId;

import java.io.Serializable;
import java.util.Date;
Expand All @@ -19,10 +22,12 @@ public class AmpIndicatorGlobalValue implements Serializable {
public static final int ACTUAL = 1;
public static final int BASE = 2;
public static final int REVISED = 3;

@InterchangeableId
@Interchangeable(fieldTitle = "Id")
@JsonIgnore
private Long id;


@JsonIgnore
/**
* The type of indicator, see {@link AmpIndicatorValue constants}
Expand All @@ -31,24 +36,29 @@ public class AmpIndicatorGlobalValue implements Serializable {
*/
private int type;

@Interchangeable(fieldTitle = "Original Value", importable = true)
@JsonProperty("originalValue")
private Double originalValue;

@Interchangeable(fieldTitle = "Original Value Date", importable = true)
@JsonSerialize(using = LocalizedDateSerializer.class)
@JsonDeserialize(using = LocalizedDateDeserializer.class)
@JsonProperty("originalValueDate")
@ApiModelProperty(dataType = "java.util.Date", example = "02/02/2023")
private Date originalValueDate;

@Interchangeable(fieldTitle = "Revised Value", importable = true)
@JsonProperty("revisedValue")
private Double revisedValue;

@Interchangeable(fieldTitle = "Revised Value Date", importable = true)
@JsonSerialize(using = LocalizedDateSerializer.class)
@JsonDeserialize(using = LocalizedDateDeserializer.class)
@JsonProperty("revisedValueDate")
@ApiModelProperty(dataType = "java.util.Date", example = "02/02/2023")
private Date revisedValueDate;

@InterchangeableBackReference
@JsonIgnore
private AmpIndicator indicator;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.digijava.module.aim.annotations.interchange.Interchangeable;
import org.digijava.module.aim.annotations.interchange.InterchangeableDiscriminator;
import org.digijava.module.aim.annotations.interchange.InterchangeableId;
import org.digijava.kernel.ampapi.endpoints.common.values.providers.LocationPossibleValuesProvider;
import org.digijava.module.aim.annotations.interchange.PossibleValues;

import java.io.Serializable;
Expand Down Expand Up @@ -48,6 +49,22 @@ public class IndicatorConnection implements Serializable, Comparable<IndicatorTh
// @VersionableCollection(fieldTitle = "Indicator Values")
protected Set<AmpIndicatorValue> values = new HashSet<>();

/**
* Disaggregation values for this indicator connection.
* Transient — not persisted by Hibernate. Populated externally (e.g. via addExtraFieldsToActivity)
*/
@Interchangeable(fieldTitle = "Disaggregation Values", importable = false)
private transient Set<AmpIndicatorDisaggregationValue> disaggregationValues = new HashSet<>();

/**
* Activity location for multi-location instances.
* When an indicator is added per location in a multi-location activity, this links to the specific
* AmpActivityLocation. The activity API replaces this id with the inner location id at export time
* (see ActivityInterchangeUtils.resolveIndicatorActivityLocations).
* Null for single-location activities.
*/
@PossibleValues(LocationPossibleValuesProvider.class)
@Interchangeable(fieldTitle = "Activity Location", importable = true, pickIdOnly = true)
private AmpActivityLocation activityLocation;

public Long getId() {
Expand Down Expand Up @@ -118,4 +135,12 @@ public String getIndicatorLocationKey() {
}
return indicatorLocationKey;
}

public Set<AmpIndicatorDisaggregationValue> getDisaggregationValues() {
return disaggregationValues;
}

public void setDisaggregationValues(Set<AmpIndicatorDisaggregationValue> disaggregationValues) {
this.disaggregationValues = disaggregationValues;
}
}
Loading
Loading