Skip to content

Commit

Permalink
MODORDERS-1102 - Order lines search results do not display fund code …
Browse files Browse the repository at this point in the history
…for orders created by data import (#943)

* Added logic to set poLine fundCode based on fundId populated during poLine mapping

* Deleted redundant call of order mapping process

(cherry picked from commit 88ac213)
  • Loading branch information
RuslanLavrov committed Jun 7, 2024
1 parent 7d02b7c commit e3c7d3d
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 2 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## 12.8.0 - Unreleased

## 12.7.4 - Released (Poppy R2 2023)
### Bug Fixes
* [MODORDERS-1121](https://folio-org.atlassian.net/browse/MODORDERS-1121) - Order lines search results do not display fund code for orders created by data import

## 12.7.3 - Released (Poppy R2 2023)
This release focused on fixing Data Import organization feature and electronic format orders for certain quantity
[Full Changelog](https://github.com/folio-org/mod-orders/compare/v12.7.2...v12.7.3)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import static org.folio.ActionProfile.Action.CREATE;
import static org.folio.ActionProfile.FolioRecord.HOLDINGS;
import static org.folio.ActionProfile.FolioRecord.INSTANCE;
Expand All @@ -30,6 +31,7 @@
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
Expand All @@ -43,6 +45,7 @@
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -107,6 +110,9 @@ public class CreateOrderEventHandler implements EventHandler {
private static final String POL_ERESOURCE_FIELD = "eresource";
private static final String POL_PHYSICAL_FIELD = "physical";
private static final String POL_CREATE_INVENTORY_FIELD = "createInventory";
private static final String POL_FUND_DISTRIBUTION_FIELD = "fundDistribution";
private static final String POL_FUND_CODE_FIELD = "code";
private static final String POL_FUND_ID_FIELD = "fundId";
private static final String PO_LINE_KEY = "PO_LINE";
private static final String RECORD_ID_HEADER = "recordId";
private static final String JOB_PROFILE_SNAPSHOT_ID_KEY = "JOB_PROFILE_SNAPSHOT_ID";
Expand All @@ -116,6 +122,8 @@ public class CreateOrderEventHandler implements EventHandler {
private static final String WORKFLOW_STATUS_PATH = "order.po.workflowStatus";
private static final String PO_LINE_ORDER_ID_KEY = "purchaseOrderId";
private static final String DEFAULT_PO_LINES_LIMIT = "1";
private static final char LEFT_BRACKET = '(';
private static final char RIGHT_BRACKET = ')';

private final PurchaseOrderHelper purchaseOrderHelper;
private final PurchaseOrderLineHelper poLineHelper;
Expand Down Expand Up @@ -178,7 +186,6 @@ public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload d
future.completeExceptionally(result.cause());
} else {
Optional<Integer> poLinesLimitOptional = extractPoLinesLimit(dataImportEventPayload);
MappingManager.map(dataImportEventPayload, new MappingContext());

RequestContext requestContext = new RequestContext(Vertx.currentContext(), okapiHeaders);
Future<JsonObject> tenantConfigFuture = configurationEntriesCache.loadConfiguration(ORDER_CONFIG_MODULE_NAME, requestContext);
Expand Down Expand Up @@ -502,6 +509,7 @@ private Future<Void> prepareMappingResult(DataImportEventPayload dataImportEvent
JsonObject orderJson = mappingResult.getJsonObject(MAPPING_RESULT_FIELD).getJsonObject(ORDER_FIELD);
JsonObject poLineJson = mappingResult.getJsonObject(MAPPING_RESULT_FIELD).getJsonObject(PO_LINES_FIELD);
calculateActivationDue(poLineJson);
ensureFundCode(poLineJson, dataImportEventPayload);
dataImportEventPayload.getContext().put(ORDER.value(), orderJson.encode());

if (WorkflowStatus.OPEN.value().equals(orderJson.getString(ORDER_STATUS_FIELD))) {
Expand All @@ -527,6 +535,35 @@ private void calculateActivationDue(JsonObject poLineJson) {
}
}

private void ensureFundCode(JsonObject poLineJson, DataImportEventPayload dataImportEventPayload) {
if (!IterableUtils.isEmpty(poLineJson.getJsonArray(POL_FUND_DISTRIBUTION_FIELD))) {
Map<String, String> idToFundName = extractFundsData(dataImportEventPayload);

poLineJson.getJsonArray(POL_FUND_DISTRIBUTION_FIELD).stream()
.map(JsonObject.class::cast)
.filter(fundDistributionJson -> isNotEmpty(fundDistributionJson.getString(POL_FUND_ID_FIELD)))
.forEach(fundDistribution -> fundDistribution.put(POL_FUND_CODE_FIELD, determineFundCode(fundDistribution, idToFundName)));
}
}

private Map<String, String> extractFundsData(DataImportEventPayload dataImportEventPayload) {
ProfileSnapshotWrapper mappingProfileWrapper = dataImportEventPayload.getCurrentNode();
MappingProfile mappingProfile = ObjectMapperTool.getMapper().convertValue(mappingProfileWrapper.getContent(), MappingProfile.class);

return mappingProfile.getMappingDetails().getMappingFields().stream()
.filter(mappingRule -> POL_FUND_DISTRIBUTION_FIELD.equals(mappingRule.getName()) && !mappingRule.getSubfields().isEmpty())
.flatMap(mappingRule -> mappingRule.getSubfields().get(0).getFields().stream())
.filter(mappingRule -> POL_FUND_ID_FIELD.equals(mappingRule.getName()))
.map(mappingRule -> ((Map<String, String>) mappingRule.getAcceptedValues()))
.findAny()
.orElse(Collections.emptyMap());
}

private String determineFundCode(JsonObject fundDistribution, Map<String, String> idToFundName) {
String fundName = idToFundName.get(fundDistribution.getString(POL_FUND_ID_FIELD));
return fundName.substring(fundName.lastIndexOf(LEFT_BRACKET) + 1, fundName.lastIndexOf(RIGHT_BRACKET));
}

private Future<Void> overrideCreateInventoryField(JsonObject poLineJson, DataImportEventPayload dataImportEventPayload) {
String profileSnapshotId = dataImportEventPayload.getContext().get(JOB_PROFILE_SNAPSHOT_ID_KEY);
Map<String, String> headers = DataImportUtils.extractOkapiHeaders(dataImportEventPayload);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.folio.rest.jaxrs.model.MappingRule;
import org.folio.rest.jaxrs.model.Physical;
import org.folio.rest.jaxrs.model.ProfileSnapshotWrapper;
import org.folio.rest.jaxrs.model.RepeatableSubfieldMapping;
import org.folio.service.dataimport.PoLineImportProgressService;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
Expand Down Expand Up @@ -91,6 +92,8 @@
import static org.folio.rest.jaxrs.model.CompositePoLine.OrderFormat.P_E_MIX;
import static org.folio.rest.jaxrs.model.EntityType.MARC_BIBLIOGRAPHIC;
import static org.folio.rest.jaxrs.model.EntityType.ORDER;
import static org.folio.rest.jaxrs.model.FundDistribution.DistributionType.PERCENTAGE;
import static org.folio.rest.jaxrs.model.MappingRule.RepeatableFieldAction.EXTEND_EXISTING;
import static org.folio.rest.jaxrs.model.ProfileSnapshotWrapper.ContentType.ACTION_PROFILE;
import static org.folio.rest.jaxrs.model.ProfileSnapshotWrapper.ContentType.JOB_PROFILE;
import static org.folio.rest.jaxrs.model.ProfileSnapshotWrapper.ContentType.MAPPING_PROFILE;
Expand Down Expand Up @@ -578,7 +581,7 @@ public void shouldCreatePendingOrderAndPublishDiCompletedEventWhenOpenStatusSpec
assertEquals(DI_ORDER_CREATED.value(), eventPayload.getEventsChain().get(eventPayload.getEventsChain().size() - 1));

CompositePurchaseOrder order = Json.decodeValue(eventPayload.getContext().get(ActionProfile.FolioRecord.ORDER.value()), CompositePurchaseOrder.class);
assertEquals(order.getApproved(), Boolean.FALSE);
assertEquals(Boolean.FALSE, order.getApproved());

verifyOrder(eventPayload);
verifyPoLine(eventPayload);
Expand Down Expand Up @@ -1501,6 +1504,61 @@ public void shouldCreatePendingOrderAndNotMapVendorMaterialSupplierAndAccessProv
assertNull(poLine.getEresource());
}

@Test
public void shouldCreatePoLineWithFundIdAndFundCode() throws InterruptedException {
// given
String expectedFundId = "7fbd5d84-62d1-44c6-9c45-6cb173998bbd";
String expectedFundCode = "AFRICAHIST";
double expectedDistributionValue = 100;

MappingRule fundDistributionsRule = new MappingRule()
.withName("fundDistribution")
.withPath("order.poLine.fundDistribution[]")
.withEnabled("true")
.withRepeatableFieldAction(EXTEND_EXISTING)
.withSubfields(List.of(new RepeatableSubfieldMapping()
.withOrder(0)
.withPath("order.poLine.fundDistribution[]")
.withFields(List.of(
new MappingRule().withPath("order.poLine.fundDistribution[].fundId").withName("fundId")
.withValue("\"African (History) (AFRICAHIST)\"")
.withAcceptedValues(new HashMap<>(Map.of(expectedFundId, "African (History) (AFRICAHIST)"))),
new MappingRule().withPath("order.poLine.fundDistribution[].value").withValue("\"100\""),
new MappingRule().withPath("order.poLine.fundDistribution[].distributionType").withValue("\"percentage\"")))
));

mappingProfile.getMappingDetails().getMappingFields().add(fundDistributionsRule);
ProfileSnapshotWrapper profileSnapshotWrapper = buildProfileSnapshotWrapper(jobProfile, actionProfile, mappingProfile);
addMockEntry(JOB_PROFILE_SNAPSHOTS_MOCK, profileSnapshotWrapper);

DataImportEventPayload dataImportEventPayload = new DataImportEventPayload()
.withJobExecutionId(jobExecutionJson.getString(ID_FIELD))
.withEventType(DI_MARC_BIB_FOR_ORDER_CREATED.value())
.withTenant(TENANT_ID)
.withOkapiUrl(OKAPI_URL)
.withToken(TOKEN)
.withContext(new HashMap<>() {{
put(MARC_BIBLIOGRAPHIC.value(), Json.encode(record));
put(JOB_PROFILE_SNAPSHOT_ID_KEY, profileSnapshotWrapper.getId());
}});

SendKeyValues<String, String> request = prepareKafkaRequest(dataImportEventPayload);

// when
kafkaCluster.send(request);

// then
DataImportEventPayload eventPayload = observeEvent(DI_COMPLETED.value());
verifyOrder(eventPayload);
CompositePoLine createdPoLine = verifyPoLine(eventPayload);
assertNotNull(createdPoLine.getFundDistribution());
assertEquals(1, createdPoLine.getFundDistribution().size());
assertEquals(expectedFundId, createdPoLine.getFundDistribution().get(0).getFundId());
assertEquals(expectedFundCode, createdPoLine.getFundDistribution().get(0).getCode());
assertEquals(expectedDistributionValue, createdPoLine.getFundDistribution().get(0).getValue());
assertEquals(PERCENTAGE, createdPoLine.getFundDistribution().get(0).getDistributionType());
}

@Test
public void shouldReturnFailedByDuplicateEventExceptionFutureWhenRecordIdIsDuplicated(TestContext context) {
Async async = context.async();
Expand Down

0 comments on commit e3c7d3d

Please sign in to comment.