diff --git a/etor/databaseMigrations/metadata.yml b/etor/databaseMigrations/metadata.yml index 3c3bffd27..1d14c95b0 100644 --- a/etor/databaseMigrations/metadata.yml +++ b/etor/databaseMigrations/metadata.yml @@ -6,8 +6,8 @@ databaseChangeLog: context: metadata comment: create status type changes: - - sql: - sql: CREATE TYPE message_status AS ENUM ('PENDING', 'DELIVERED', 'FAILED') + - sql: + sql: CREATE TYPE message_status AS ENUM ('PENDING', 'DELIVERED', 'FAILED') rollback: - sql: sql: DROP TYPE message_status @@ -19,7 +19,7 @@ databaseChangeLog: context: metadata comment: create partner metadata table changes: - - createTable: + - createTable: tableName: metadata columns: - column: @@ -60,8 +60,8 @@ databaseChangeLog: context: metadata comment: create message type changes: - - sql: - sql: CREATE TYPE message_type AS ENUM ('RESULT', 'ORDER') + - sql: + sql: CREATE TYPE message_type AS ENUM ('RESULT', 'ORDER') rollback: - sql: sql: DROP TYPE message_type @@ -109,3 +109,46 @@ databaseChangeLog: - column: name: receiving_facility_id type: varchar(227) + - changeSet: + id: 6 + author: samuel.aquino + labels: update-metadata-table + context: metadata + comment: update partner metadata table for order and result linking using jsonb + changes: + - renameColumn: + columnDataType: varchar(227) + oldColumnName: sending_application_id + newColumnName: sending_application_details + tableName: metadata + - renameColumn: + columnDataType: varchar(227) + oldColumnName: sending_facility_id + newColumnName: sending_facility_details + tableName: metadata + - renameColumn: + columnDataType: varchar(227) + oldColumnName: receiving_application_id + newColumnName: receiving_application_details + tableName: metadata + - renameColumn: + columnDataType: varchar(227) + oldColumnName: receiving_facility_id + newColumnName: receiving_facility_details + tableName: metadata + - modifyDataType: + columnName: sending_application_details + newDataType: jsonb + tableName: metadata + - modifyDataType: + columnName: sending_facility_details + newDataType: jsonb + tableName: metadata + - modifyDataType: + columnName: receiving_application_details + newDataType: jsonb + tableName: metadata + - modifyDataType: + columnName: receiving_facility_details + newDataType: jsonb + tableName: metadata diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/messages/MessageHdDataType.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/messages/MessageHdDataType.java index 9ff26d0ca..05e0f513c 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/messages/MessageHdDataType.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/messages/MessageHdDataType.java @@ -6,4 +6,8 @@ * identifier (ID), and the type of the universal ID. HD reference: HD-DataType */ -public record MessageHdDataType(String namespace, String universalId, String universalIdType) {} +public record MessageHdDataType(String namespace, String universalId, String universalIdType) { + + // Constructor for Jackson Mapping + public MessageHdDataType {} +} diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/messages/SendMessageHelper.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/messages/SendMessageHelper.java index 6c7351cd6..66e381e66 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/messages/SendMessageHelper.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/messages/SendMessageHelper.java @@ -20,7 +20,14 @@ public static SendMessageHelper getInstance() { private SendMessageHelper() {} public void savePartnerMetadataForReceivedMessage( - String receivedSubmissionId, int messageHash, PartnerMetadataMessageType messageType) { + String receivedSubmissionId, + int messageHash, + PartnerMetadataMessageType messageType, + MessageHdDataType sendingApplicationDetails, + MessageHdDataType sendingFacilityDetails, + MessageHdDataType receivingApplicationDetails, + MessageHdDataType receivingFacilityDetails, + String placerOrderNumber) { if (receivedSubmissionId == null) { logger.logWarning( "Received submissionId is null so not saving metadata for received message"); @@ -30,7 +37,14 @@ public void savePartnerMetadataForReceivedMessage( String stringMessageHash = String.valueOf(messageHash); partnerMetadataOrchestrator.updateMetadataForReceivedMessage( - receivedSubmissionId, stringMessageHash, messageType); + receivedSubmissionId, + stringMessageHash, + messageType, + sendingApplicationDetails, + sendingFacilityDetails, + receivingApplicationDetails, + receivingFacilityDetails, + placerOrderNumber); } catch (PartnerMetadataException e) { logger.logError( "Unable to save metadata for receivedSubmissionId " + receivedSubmissionId, e); diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadata.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadata.java index 738c00aa3..3f230335e 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadata.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadata.java @@ -1,5 +1,6 @@ package gov.hhs.cdc.trustedintermediary.etor.metadata.partner; +import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType; import java.time.Instant; /** @@ -24,7 +25,12 @@ public record PartnerMetadata( String hash, PartnerMetadataStatus deliveryStatus, String failureReason, - PartnerMetadataMessageType messageType) { + PartnerMetadataMessageType messageType, + MessageHdDataType sendingApplicationDetails, + MessageHdDataType sendingFacilityDetails, + MessageHdDataType receivingApplicationDetails, + MessageHdDataType receivingFacilityDetails, + String placerOrderNumber) { // Below is for defaulting status when null public PartnerMetadata { @@ -40,7 +46,12 @@ public PartnerMetadata( Instant timeDelivered, String hash, PartnerMetadataStatus deliveryStatus, - PartnerMetadataMessageType messageType) { + PartnerMetadataMessageType messageType, + MessageHdDataType sendingApplicationDetails, + MessageHdDataType sendingFacilityDetails, + MessageHdDataType receivingApplicationDetails, + MessageHdDataType receivingFacilityDetails, + String placerOrderNumber) { this( receivedSubmissionId, null, @@ -51,26 +62,42 @@ public PartnerMetadata( hash, deliveryStatus, null, - messageType); - } - - public PartnerMetadata(String receivedSubmissionId, String hash) { - this(receivedSubmissionId, null, null, null, null, null, hash, null, null, null); + messageType, + sendingApplicationDetails, + sendingFacilityDetails, + receivingApplicationDetails, + receivingFacilityDetails, + placerOrderNumber); } public PartnerMetadata( - String receivedSubmissionId, String hash, PartnerMetadataMessageType messageType) { - this(receivedSubmissionId, null, null, null, null, null, hash, null, null, messageType); + String receivedSubmissionId, + String hash, + PartnerMetadataMessageType messageType, + MessageHdDataType sendingApplicationDetails, + MessageHdDataType sendingFacilityDetails, + MessageHdDataType receivingApplicationDetails, + MessageHdDataType receivingFacilityDetails, + String placerOrderNumber) { + this( + receivedSubmissionId, + null, + null, + null, + null, + null, + hash, + null, + null, + messageType, + sendingApplicationDetails, + sendingFacilityDetails, + receivingApplicationDetails, + receivingFacilityDetails, + placerOrderNumber); } public PartnerMetadata(String receivedSubmissionId, PartnerMetadataStatus deliveryStatus) { - this(receivedSubmissionId, null, null, null, null, null, null, deliveryStatus, null, null); - } - - public PartnerMetadata( - String receivedSubmissionId, - PartnerMetadataStatus deliveryStatus, - PartnerMetadataMessageType messageType) { this( receivedSubmissionId, null, @@ -81,7 +108,12 @@ public PartnerMetadata( null, deliveryStatus, null, - messageType); + null, + null, + null, + null, + null, + null); } public PartnerMetadata withSentSubmissionId(String sentSubmissionId) { @@ -95,7 +127,12 @@ public PartnerMetadata withSentSubmissionId(String sentSubmissionId) { this.hash, this.deliveryStatus, this.failureReason, - this.messageType); + this.messageType, + this.sendingApplicationDetails, + this.sendingFacilityDetails, + this.receivingApplicationDetails, + this.receivingFacilityDetails, + this.placerOrderNumber); } public PartnerMetadata withReceiver(String receiver) { @@ -109,7 +146,12 @@ public PartnerMetadata withReceiver(String receiver) { this.hash, this.deliveryStatus, this.failureReason, - this.messageType); + this.messageType, + this.sendingApplicationDetails, + this.sendingFacilityDetails, + this.receivingApplicationDetails, + this.receivingFacilityDetails, + this.placerOrderNumber); } public PartnerMetadata withTimeDelivered(Instant timeDelivered) { @@ -123,7 +165,12 @@ public PartnerMetadata withTimeDelivered(Instant timeDelivered) { this.hash, this.deliveryStatus, this.failureReason, - this.messageType); + this.messageType, + this.sendingApplicationDetails, + this.sendingFacilityDetails, + this.receivingApplicationDetails, + this.receivingFacilityDetails, + this.placerOrderNumber); } public PartnerMetadata withDeliveryStatus(PartnerMetadataStatus deliveryStatus) { @@ -137,7 +184,12 @@ public PartnerMetadata withDeliveryStatus(PartnerMetadataStatus deliveryStatus) this.hash, deliveryStatus, this.failureReason, - this.messageType); + this.messageType, + this.sendingApplicationDetails, + this.sendingFacilityDetails, + this.receivingApplicationDetails, + this.receivingFacilityDetails, + this.placerOrderNumber); } public PartnerMetadata withFailureMessage(String failureMessage) { @@ -151,6 +203,11 @@ public PartnerMetadata withFailureMessage(String failureMessage) { this.hash, this.deliveryStatus, failureMessage, - this.messageType); + this.messageType, + this.sendingApplicationDetails, + this.sendingFacilityDetails, + this.receivingApplicationDetails, + this.receivingFacilityDetails, + this.placerOrderNumber); } } diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataOrchestrator.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataOrchestrator.java index 9ca804218..fcc057751 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataOrchestrator.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataOrchestrator.java @@ -1,6 +1,7 @@ package gov.hhs.cdc.trustedintermediary.etor.metadata.partner; import gov.hhs.cdc.trustedintermediary.etor.RSEndpointClient; +import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType; import gov.hhs.cdc.trustedintermediary.external.reportstream.ReportStreamEndpointClientException; import gov.hhs.cdc.trustedintermediary.wrappers.Logger; import gov.hhs.cdc.trustedintermediary.wrappers.formatter.Formatter; @@ -36,7 +37,14 @@ public static PartnerMetadataOrchestrator getInstance() { private PartnerMetadataOrchestrator() {} public void updateMetadataForReceivedMessage( - String receivedSubmissionId, String messageHash, PartnerMetadataMessageType messageType) + String receivedSubmissionId, + String messageHash, + PartnerMetadataMessageType messageType, + MessageHdDataType sendingApplicationDetails, + MessageHdDataType sendingFacilityDetails, + MessageHdDataType receivingApplicationDetails, + MessageHdDataType receivingFacilityDetails, + String placerOrderNumber) throws PartnerMetadataException { logger.logInfo( @@ -72,7 +80,15 @@ public void updateMetadataForReceivedMessage( "Unable to retrieve metadata from RS delivery API, but writing basic metadata entry anyway for received submission ID {}", receivedSubmissionId); PartnerMetadata partnerMetadata = - new PartnerMetadata(receivedSubmissionId, messageHash, messageType); + new PartnerMetadata( + receivedSubmissionId, + messageHash, + messageType, + sendingApplicationDetails, + sendingFacilityDetails, + receivingApplicationDetails, + receivingFacilityDetails, + placerOrderNumber); partnerMetadataStorage.saveMetadata(partnerMetadata); throw new PartnerMetadataException( @@ -92,7 +108,12 @@ public void updateMetadataForReceivedMessage( null, messageHash, PartnerMetadataStatus.PENDING, - messageType); + messageType, + sendingApplicationDetails, + sendingFacilityDetails, + receivingApplicationDetails, + receivingFacilityDetails, + placerOrderNumber); partnerMetadataStorage.saveMetadata(partnerMetadata); } diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/orders/SendOrderUseCase.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/orders/SendOrderUseCase.java index a3f1f6c5d..a6b3485ff 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/orders/SendOrderUseCase.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/orders/SendOrderUseCase.java @@ -29,7 +29,14 @@ public void convertAndSend(final Order order, String receivedSubmissionId) throws UnableToSendMessageException { sendMessageHelper.savePartnerMetadataForReceivedMessage( - receivedSubmissionId, order.hashCode(), PartnerMetadataMessageType.ORDER); + receivedSubmissionId, + order.hashCode(), + PartnerMetadataMessageType.ORDER, + order.getSendingApplicationDetails(), + order.getSendingFacilityDetails(), + order.getReceivingApplicationDetails(), + order.getReceivingFacilityDetails(), + order.getPlacerOrderNumber()); var omlOrder = converter.convertToOmlOrder(order); metadata.put(order.getFhirResourceId(), EtorMetadataStep.ORDER_CONVERTED_TO_OML); diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/results/SendResultUseCase.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/results/SendResultUseCase.java index 20925f2d0..673ab1012 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/results/SendResultUseCase.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/results/SendResultUseCase.java @@ -31,7 +31,14 @@ public static SendResultUseCase getInstance() { public void convertAndSend(Result result, String receivedSubmissionId) throws UnableToSendMessageException { sendMessageHelper.savePartnerMetadataForReceivedMessage( - receivedSubmissionId, result.hashCode(), PartnerMetadataMessageType.RESULT); + receivedSubmissionId, + result.hashCode(), + PartnerMetadataMessageType.RESULT, + result.getSendingApplicationDetails(), + result.getSendingFacilityDetails(), + result.getReceivingApplicationDetails(), + result.getReceivingFacilityDetails(), + result.getPlacerOrderNumber()); var convertedResult = converter.addEtorProcessingTag(result); metadata.put( diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/DatabasePartnerMetadataStorage.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/DatabasePartnerMetadataStorage.java index 4753d5cef..abd61f6e6 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/DatabasePartnerMetadataStorage.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/DatabasePartnerMetadataStorage.java @@ -4,6 +4,8 @@ import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataException; import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataStorage; import gov.hhs.cdc.trustedintermediary.wrappers.Logger; +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.Formatter; +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.FormatterProcessingException; import java.sql.SQLException; import java.sql.Timestamp; import java.sql.Types; @@ -18,6 +20,8 @@ public class DatabasePartnerMetadataStorage implements PartnerMetadataStorage { @Inject DbDao dao; @Inject Logger logger; + + @Inject Formatter formatter; private static final DatabasePartnerMetadataStorage INSTANCE = new DatabasePartnerMetadataStorage(); @@ -35,6 +39,8 @@ public Optional readMetadata(final String uniqueId) return Optional.ofNullable(data); } catch (SQLException e) { throw new PartnerMetadataException("Error retrieving metadata", e); + } catch (FormatterProcessingException e) { + throw new PartnerMetadataException("Error formatting metadata", e); } } @@ -42,54 +48,13 @@ public Optional readMetadata(final String uniqueId) public void saveMetadata(final PartnerMetadata metadata) throws PartnerMetadataException { logger.logInfo("saving the metadata"); - List columns = - List.of( - new DbColumn( - "received_message_id", - metadata.receivedSubmissionId(), - false, - Types.VARCHAR), - new DbColumn( - "sent_message_id", - metadata.sentSubmissionId(), - true, - Types.VARCHAR), - new DbColumn("sender", metadata.sender(), false, Types.VARCHAR), - new DbColumn("receiver", metadata.receiver(), true, Types.VARCHAR), - new DbColumn("hash_of_message", metadata.hash(), false, Types.VARCHAR), - new DbColumn( - "time_received", - metadata.timeReceived() != null - ? Timestamp.from(metadata.timeReceived()) - : null, - false, - Types.TIMESTAMP), - new DbColumn( - "time_delivered", - metadata.timeDelivered() != null - ? Timestamp.from(metadata.timeDelivered()) - : null, - true, - Types.TIMESTAMP), - new DbColumn( - "delivery_status", - metadata.deliveryStatus().toString(), - true, - Types.OTHER), - new DbColumn( - "failure_reason", metadata.failureReason(), true, Types.VARCHAR), - new DbColumn( - "message_type", - metadata.messageType() != null - ? metadata.messageType().toString() - : null, - false, - Types.OTHER)); - try { + List columns = createDbColumnsFromMetadata(metadata); dao.upsertData("metadata", columns, "received_message_id"); } catch (SQLException e) { throw new PartnerMetadataException("Error saving metadata", e); + } catch (FormatterProcessingException e) { + throw new PartnerMetadataException("Error parsing metadata", e); } } @@ -101,7 +66,67 @@ public Set readMetadataForSender(String sender) consolidatedMetadata = dao.fetchMetadataForSender(sender); } catch (SQLException e) { throw new PartnerMetadataException("Error retrieving consolidated metadata", e); + } catch (FormatterProcessingException e) { + throw new PartnerMetadataException("Error formatting consolidated metadata", e); } return consolidatedMetadata; } + + private List createDbColumnsFromMetadata(PartnerMetadata metadata) + throws FormatterProcessingException { + return List.of( + new DbColumn( + "received_message_id", + metadata.receivedSubmissionId(), + false, + Types.VARCHAR), + new DbColumn("sent_message_id", metadata.sentSubmissionId(), true, Types.VARCHAR), + new DbColumn("sender", metadata.sender(), false, Types.VARCHAR), + new DbColumn("receiver", metadata.receiver(), true, Types.VARCHAR), + new DbColumn("hash_of_message", metadata.hash(), false, Types.VARCHAR), + new DbColumn( + "time_received", + metadata.timeReceived() != null + ? Timestamp.from(metadata.timeReceived()) + : null, + false, + Types.TIMESTAMP), + new DbColumn( + "time_delivered", + metadata.timeDelivered() != null + ? Timestamp.from(metadata.timeDelivered()) + : null, + true, + Types.TIMESTAMP), + new DbColumn( + "delivery_status", metadata.deliveryStatus().toString(), true, Types.OTHER), + new DbColumn("failure_reason", metadata.failureReason(), true, Types.VARCHAR), + new DbColumn( + "message_type", + metadata.messageType() != null ? metadata.messageType().toString() : null, + false, + Types.OTHER), + new DbColumn( + "placer_order_number", metadata.placerOrderNumber(), false, Types.VARCHAR), + new DbColumn( + "sending_application_details", + formatter.convertToJsonString(metadata.sendingApplicationDetails()), + false, + Types.OTHER), + new DbColumn( + "sending_facility_details", + formatter.convertToJsonString(metadata.sendingFacilityDetails()), + false, + Types.OTHER), + new DbColumn( + "receiving_application_details", + formatter.convertToJsonString(metadata.receivingApplicationDetails()), + false, + Types.OTHER), + new DbColumn( + "receiving_facility_details", + formatter.convertToJsonString(metadata.receivingFacilityDetails()), + false, + Types.OTHER)); + } } diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/DbDao.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/DbDao.java index 0ec8f87ac..1b0420372 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/DbDao.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/DbDao.java @@ -1,6 +1,7 @@ package gov.hhs.cdc.trustedintermediary.external.database; import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadata; +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.FormatterProcessingException; import java.sql.SQLException; import java.util.List; import java.util.Set; @@ -10,7 +11,8 @@ public interface DbDao { void upsertData(String tableName, List values, String conflictColumnName) throws SQLException; - Set fetchMetadataForSender(String sender) throws SQLException; + Set fetchMetadataForSender(String sender) + throws SQLException, FormatterProcessingException; - Object fetchMetadata(String uniqueId) throws SQLException; + Object fetchMetadata(String uniqueId) throws SQLException, FormatterProcessingException; } diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/PostgresDao.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/PostgresDao.java index bf80ae619..1656188bc 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/PostgresDao.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/external/database/PostgresDao.java @@ -4,6 +4,9 @@ import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataMessageType; import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataStatus; import gov.hhs.cdc.trustedintermediary.wrappers.database.ConnectionPool; +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.Formatter; +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.FormatterProcessingException; +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.TypeReference; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -22,6 +25,8 @@ public class PostgresDao implements DbDao { @Inject ConnectionPool connectionPool; + @Inject Formatter formatter; + private PostgresDao() {} public static PostgresDao getInstance() { @@ -92,7 +97,8 @@ public void upsertData(String tableName, List values, String conflictC } @Override - public Set fetchMetadataForSender(String sender) throws SQLException { + public Set fetchMetadataForSender(String sender) + throws SQLException, FormatterProcessingException { try (Connection conn = connectionPool.getConnection(); PreparedStatement statement = @@ -111,7 +117,8 @@ public Set fetchMetadataForSender(String sender) throws SQLExce } @Override - public PartnerMetadata fetchMetadata(String submissionId) throws SQLException { + public PartnerMetadata fetchMetadata(String submissionId) + throws SQLException, FormatterProcessingException { try (Connection conn = connectionPool.getConnection(); PreparedStatement statement = conn.prepareStatement( @@ -134,7 +141,8 @@ private void removeLastTwoCharacters(StringBuilder stringBuilder) { stringBuilder.delete(stringBuilder.length() - 2, stringBuilder.length()); } - private PartnerMetadata partnerMetadataFromResultSet(ResultSet resultSet) throws SQLException { + private PartnerMetadata partnerMetadataFromResultSet(ResultSet resultSet) + throws SQLException, FormatterProcessingException { Instant timeReceived = null; Instant timeDelivered = null; Timestamp timestampReceived = resultSet.getTimestamp("time_received"); @@ -157,6 +165,18 @@ private PartnerMetadata partnerMetadataFromResultSet(ResultSet resultSet) throws resultSet.getString("hash_of_message"), PartnerMetadataStatus.valueOf(resultSet.getString("delivery_status")), resultSet.getString("failure_reason"), - PartnerMetadataMessageType.valueOf(resultSet.getString("message_type"))); + PartnerMetadataMessageType.valueOf(resultSet.getString("message_type")), + formatter.convertJsonToObject( + resultSet.getString("sending_application_details"), + new TypeReference<>() {}), + formatter.convertJsonToObject( + resultSet.getString("sending_facility_details"), new TypeReference<>() {}), + formatter.convertJsonToObject( + resultSet.getString("receiving_application_details"), + new TypeReference<>() {}), + formatter.convertJsonToObject( + resultSet.getString("receiving_facility_details"), + new TypeReference<>() {}), + resultSet.getString("placer_order_number")); } } diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy index 8d6f6d9e3..10309131d 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy @@ -12,6 +12,7 @@ import gov.hhs.cdc.trustedintermediary.etor.demographics.ConvertAndSendDemograph import gov.hhs.cdc.trustedintermediary.etor.demographics.Demographics import gov.hhs.cdc.trustedintermediary.etor.demographics.PatientDemographicsController import gov.hhs.cdc.trustedintermediary.etor.demographics.PatientDemographicsResponse +import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType import gov.hhs.cdc.trustedintermediary.etor.messages.MessageRequestHandler import gov.hhs.cdc.trustedintermediary.etor.messages.UnableToSendMessageException import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadata @@ -22,7 +23,6 @@ import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataOrch import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataStatus import gov.hhs.cdc.trustedintermediary.etor.operationoutcomes.FhirMetadata import gov.hhs.cdc.trustedintermediary.etor.orders.OrderController -import gov.hhs.cdc.trustedintermediary.etor.orders.OrderConverter import gov.hhs.cdc.trustedintermediary.etor.orders.OrderResponse import gov.hhs.cdc.trustedintermediary.etor.orders.SendOrderUseCase import gov.hhs.cdc.trustedintermediary.etor.results.ResultController @@ -233,8 +233,13 @@ class EtorDomainRegistrationTest extends Specification { def request = new DomainRequest() request.setPathParams(["id": "metadataId"]) + def sendingAppDetails = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacilityDetails = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingAppDetails = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacilityDetails = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + def mockPartnerMetadataOrchestrator = Mock(PartnerMetadataOrchestrator) - mockPartnerMetadataOrchestrator.getMetadata(_ as String) >> Optional.ofNullable(new PartnerMetadata("receivedSubmissionId", "sender", Instant.now(), null, "hash", PartnerMetadataStatus.DELIVERED, PartnerMetadataMessageType.ORDER)) + mockPartnerMetadataOrchestrator.getMetadata(_ as String) >> Optional.ofNullable(new PartnerMetadata("receivedSubmissionId", "sender", Instant.now(), null, "hash", PartnerMetadataStatus.DELIVERED, PartnerMetadataMessageType.ORDER, sendingAppDetails, sendingFacilityDetails, receivingAppDetails, receivingFacilityDetails, "placer_order_number")) TestApplicationContext.register(PartnerMetadataOrchestrator, mockPartnerMetadataOrchestrator) def mockResponseHelper = Mock(DomainResponseHelper) diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/messages/SendMessageHelperTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/messages/SendMessageHelperTest.groovy index 0eb628bc7..75cde753c 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/messages/SendMessageHelperTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/messages/SendMessageHelperTest.groovy @@ -22,24 +22,27 @@ class SendMessageHelperTest extends Specification { } def "savePartnerMetadataForReceivedMessage works"() { given: - def hashCode = new Random().nextInt() - def messageType = PartnerMetadataMessageType.RESULT - def receivedSubmissionId = "receivedId" + def sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") when: - SendMessageHelper.getInstance().savePartnerMetadataForReceivedMessage(receivedSubmissionId, hashCode, messageType) + SendMessageHelper.getInstance().savePartnerMetadataForReceivedMessage("receivedId", new Random().nextInt(), PartnerMetadataMessageType.RESULT,sendingApp, sendingFacility, receivingApp, receivingFacility, "placer_order_number") then: - 1 * mockOrchestrator.updateMetadataForReceivedMessage(_, _, _) + 1 * mockOrchestrator.updateMetadataForReceivedMessage(_, _, _, _, _, _, _, _) } def "savePartnerMetadataForReceivedMessage should log warnings for null receivedSubmissionId"() { given: - def hashCode = new Random().nextInt() - def messageType = PartnerMetadataMessageType.RESULT + def sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") when: - SendMessageHelper.getInstance().savePartnerMetadataForReceivedMessage(null, hashCode, messageType) + SendMessageHelper.getInstance().savePartnerMetadataForReceivedMessage(null, new Random().nextInt(), PartnerMetadataMessageType.RESULT, sendingApp, sendingFacility, receivingApp, receivingFacility,"placer_order_number") then: 1 * mockLogger.logWarning(_) @@ -50,10 +53,15 @@ class SendMessageHelperTest extends Specification { def hashCode = new Random().nextInt() def messageType = PartnerMetadataMessageType.RESULT def receivedSubmissionId = "receivedId" - mockOrchestrator.updateMetadataForReceivedMessage(receivedSubmissionId, _ as String, messageType) >> { throw new PartnerMetadataException("Error") } + def sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + def placerOrderNumber = "placer_order_number" + mockOrchestrator.updateMetadataForReceivedMessage(receivedSubmissionId, _ as String, messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) >> { throw new PartnerMetadataException("Error") } when: - SendMessageHelper.getInstance().savePartnerMetadataForReceivedMessage(receivedSubmissionId, hashCode, messageType) + SendMessageHelper.getInstance().savePartnerMetadataForReceivedMessage(receivedSubmissionId, hashCode, messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) then: 1 * mockLogger.logError(_, _) diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataOrchestratorTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataOrchestratorTest.groovy index ae7b963bc..119d54150 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataOrchestratorTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataOrchestratorTest.groovy @@ -2,6 +2,7 @@ package gov.hhs.cdc.trustedintermediary.etor.metadata.partner import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext import gov.hhs.cdc.trustedintermediary.etor.RSEndpointClient +import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType import gov.hhs.cdc.trustedintermediary.etor.orders.OrderConverter import gov.hhs.cdc.trustedintermediary.external.hapi.HapiOrderConverter import gov.hhs.cdc.trustedintermediary.external.jackson.Jackson @@ -17,6 +18,11 @@ class PartnerMetadataOrchestratorTest extends Specification { private def mockPartnerMetadataStorage private def mockClient private def mockFormatter + private def sendingApp + private def sendingFacility + private def receivingApp + private def receivingFacility + private def placerOrderNumber def setup() { TestApplicationContext.reset() @@ -25,6 +31,12 @@ class PartnerMetadataOrchestratorTest extends Specification { mockFormatter = Mock(Formatter) mockClient = Mock(RSEndpointClient) + sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + placerOrderNumber = "placer_order_number" + TestApplicationContext.register(PartnerMetadataOrchestrator, PartnerMetadataOrchestrator.getInstance()) TestApplicationContext.register(OrderConverter, HapiOrderConverter.getInstance()) TestApplicationContext.register(PartnerMetadataStorage, mockPartnerMetadataStorage) @@ -47,7 +59,6 @@ class PartnerMetadataOrchestratorTest extends Specification { def bearerToken = "token" def messageType = PartnerMetadataMessageType.RESULT def deliveryStatus = PartnerMetadataStatus.PENDING - def rsDeliveryApiResponse = """ { "deliveryId": 20, @@ -76,12 +87,12 @@ class PartnerMetadataOrchestratorTest extends Specification { """ when: - PartnerMetadataOrchestrator.getInstance().updateMetadataForReceivedMessage(receivedSubmissionId, hashCode, messageType) + PartnerMetadataOrchestrator.getInstance().updateMetadataForReceivedMessage(receivedSubmissionId, hashCode, messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) then: 1 * mockClient.getRsToken() >> bearerToken 1 * mockClient.requestDeliveryEndpoint(receivedSubmissionId, bearerToken) >> rsDeliveryApiResponse - 1 * mockPartnerMetadataStorage.saveMetadata(new PartnerMetadata(receivedSubmissionId, "PLACE_HOLDER", Instant.parse(timestamp), null, hashCode, deliveryStatus, messageType)) + 1 * mockPartnerMetadataStorage.saveMetadata(new PartnerMetadata(receivedSubmissionId, "PLACE_HOLDER", Instant.parse(timestamp), null, hashCode, deliveryStatus, messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber)) } def "updateMetadataForSentMessage test case when sentSubmissionId is null"() { @@ -126,13 +137,12 @@ class PartnerMetadataOrchestratorTest extends Specification { def "updateMetadataForReceivedMessage throws PartnerMetadataException on client error"() { given: def receivedSubmissionId = "receivedSubmissionId" - def messageType = PartnerMetadataMessageType.RESULT mockClient.getRsToken() >> "token" mockClient.requestDeliveryEndpoint(_ as String, _ as String) >> { throw new ReportStreamEndpointClientException("Client error", new Exception()) } when: - PartnerMetadataOrchestrator.getInstance().updateMetadataForReceivedMessage(receivedSubmissionId, "hash", messageType) + PartnerMetadataOrchestrator.getInstance().updateMetadataForReceivedMessage(receivedSubmissionId, "hash", PartnerMetadataMessageType.RESULT, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) then: 1 * mockPartnerMetadataStorage.saveMetadata(_ as PartnerMetadata) >> { PartnerMetadata metadata -> @@ -152,7 +162,7 @@ class PartnerMetadataOrchestratorTest extends Specification { mockFormatter.convertJsonToObject(rsDeliveryApiResponse, _ as TypeReference) >> { throw new FormatterProcessingException("Formatter error", new Exception()) } when: - PartnerMetadataOrchestrator.getInstance().updateMetadataForReceivedMessage(receivedSubmissionId, "hash", messageType) + PartnerMetadataOrchestrator.getInstance().updateMetadataForReceivedMessage(receivedSubmissionId, "hash", messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) then: thrown(PartnerMetadataException) @@ -160,16 +170,14 @@ class PartnerMetadataOrchestratorTest extends Specification { def "updateMetadataForReceivedMessage throws PartnerMetadataException on formatter error due to unexpected response format"() { given: - def receivedSubmissionId = "receivedSubmissionId" def wrongFormatResponse = "{\"someotherkey\": \"value\"}" - def messageType = PartnerMetadataMessageType.RESULT mockClient.getRsToken() >> "token" mockClient.requestDeliveryEndpoint(_ as String, _ as String) >> wrongFormatResponse mockFormatter.convertJsonToObject(wrongFormatResponse, _ as TypeReference) >> [someotherkey: "value"] when: - PartnerMetadataOrchestrator.getInstance().updateMetadataForReceivedMessage(receivedSubmissionId, "hash", messageType) + PartnerMetadataOrchestrator.getInstance().updateMetadataForReceivedMessage("receivedSubmissionId", "hash", PartnerMetadataMessageType.RESULT, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) then: thrown(PartnerMetadataException) @@ -186,7 +194,7 @@ class PartnerMetadataOrchestratorTest extends Specification { mockFormatter.convertJsonToObject(wrongFormatResponse, _ as TypeReference) >> [originalIngestion: []] when: - PartnerMetadataOrchestrator.getInstance().updateMetadataForReceivedMessage(receivedSubmissionId, "hash", messageType) + PartnerMetadataOrchestrator.getInstance().updateMetadataForReceivedMessage(receivedSubmissionId, "hash", messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) then: thrown(PartnerMetadataException) @@ -196,7 +204,7 @@ class PartnerMetadataOrchestratorTest extends Specification { given: def receivedSubmissionId = "receivedSubmissionId" def sentSubmissionId = "sentSubmissionId" - def partnerMetadata = new PartnerMetadata(receivedSubmissionId, "sender", Instant.now(), null, "hash", PartnerMetadataStatus.PENDING, PartnerMetadataMessageType.ORDER) + def partnerMetadata = new PartnerMetadata(receivedSubmissionId, "sender", Instant.now(), null, "hash", PartnerMetadataStatus.PENDING, PartnerMetadataMessageType.ORDER, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) def updatedPartnerMetadata = partnerMetadata.withSentSubmissionId(sentSubmissionId) when: @@ -222,9 +230,7 @@ class PartnerMetadataOrchestratorTest extends Specification { def "getMetadata throws PartnerMetadataException on client error"() { given: def receivedSubmissionId = "receivedSubmissionId" - def sentSubmissionId = "sentSubmissionId" - def messageType = PartnerMetadataMessageType.RESULT - def partnerMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, "sender", null, Instant.now(), null, "hash", PartnerMetadataStatus.PENDING, "failureReason", messageType) + def partnerMetadata = new PartnerMetadata(receivedSubmissionId, "sentSubmissionId", "sender", null, Instant.now(), null, "hash", PartnerMetadataStatus.PENDING, "failureReason", PartnerMetadataMessageType.RESULT, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) mockPartnerMetadataStorage.readMetadata(receivedSubmissionId) >> Optional.of(partnerMetadata) mockClient.getRsToken() >> "token" @@ -240,10 +246,8 @@ class PartnerMetadataOrchestratorTest extends Specification { def "getMetadata throws PartnerMetadataException on formatter error"() { given: def receivedSubmissionId = "receivedSubmissionId" - def sentSubmissionId = "sentSubmissionId" - def messageType = PartnerMetadataMessageType.RESULT def rsHistoryApiResponse = "{\"destinations\": [{\"organization_id\": \"org\", \"service\": \"service\"}]}" - def partnerMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, "sender", null, Instant.now(), null, "hash", PartnerMetadataStatus.PENDING, "failureReason", messageType) + def partnerMetadata = new PartnerMetadata(receivedSubmissionId, "sentSubmissionId", "sender", null, Instant.now(), null, "hash", PartnerMetadataStatus.PENDING, "failureReason", PartnerMetadataMessageType.RESULT, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) mockPartnerMetadataStorage.readMetadata(receivedSubmissionId) >> Optional.of(partnerMetadata) mockClient.getRsToken() >> "token" @@ -260,8 +264,7 @@ class PartnerMetadataOrchestratorTest extends Specification { def "getMetadata retrieves metadata successfully with the sender already filled"() { given: def receivedSubmissionId = "receivedSubmissionId" - def messageType = PartnerMetadataMessageType.RESULT - def metadata = new PartnerMetadata(receivedSubmissionId, "sentSubmissionId", "sender", "receiver", Instant.now(), null, "hash", PartnerMetadataStatus.DELIVERED, null, messageType) + def metadata = new PartnerMetadata(receivedSubmissionId, "sentSubmissionId", "sender", "receiver", Instant.now(), null, "hash", PartnerMetadataStatus.DELIVERED, null, PartnerMetadataMessageType.RESULT, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) when: def result = PartnerMetadataOrchestrator.getInstance().getMetadata(receivedSubmissionId) @@ -276,8 +279,7 @@ class PartnerMetadataOrchestratorTest extends Specification { def "getMetadata retrieves metadata successfully when receiver is present and sentSubmissionId is missing"() { given: def receivedSubmissionId = "receivedSubmissionId" - def messageType = PartnerMetadataMessageType.RESULT - def metadata = new PartnerMetadata(receivedSubmissionId, null, "sender", "receiver", Instant.now(), null, "hash", PartnerMetadataStatus.DELIVERED, null, messageType) + def metadata = new PartnerMetadata(receivedSubmissionId, null, "sender", "receiver", Instant.now(), null, "hash", PartnerMetadataStatus.DELIVERED, null, PartnerMetadataMessageType.RESULT, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) when: def result = PartnerMetadataOrchestrator.getInstance().getMetadata(receivedSubmissionId) @@ -299,8 +301,8 @@ class PartnerMetadataOrchestratorTest extends Specification { def bearerToken = "token" def messageType = PartnerMetadataMessageType.RESULT def rsHistoryApiResponse = "{\"actualCompletionAt\": \"2023-10-24T19:48:26.921Z\",\"destinations\": [{\"organization_id\": \"org\", \"service\": \"service\"}]}" - def missingReceiverMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, null, timestamp, timeDelivered, hashCode, PartnerMetadataStatus.DELIVERED, "", messageType) - def expectedMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, "org.service", timestamp, timeDelivered, hashCode, PartnerMetadataStatus.DELIVERED, "", messageType) + def missingReceiverMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, null, timestamp, timeDelivered, hashCode, PartnerMetadataStatus.DELIVERED, "", messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) + def expectedMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, "org.service", timestamp, timeDelivered, hashCode, PartnerMetadataStatus.DELIVERED, "", messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) mockClient.getRsToken() >> bearerToken mockClient.requestHistoryEndpoint(sentSubmissionId, bearerToken) >> rsHistoryApiResponse @@ -334,8 +336,8 @@ class PartnerMetadataOrchestratorTest extends Specification { def bearerToken = "token" def messageType = PartnerMetadataMessageType.RESULT def rsHistoryApiResponse = "{\"destinations\": [{\"organization_id\": \"org\", \"service\": \"service\"}]}" - def missingReceiverMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timestamp, null, hashCode, PartnerMetadataStatus.PENDING, null, messageType) - def expectedMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timestamp, null, hashCode, PartnerMetadataStatus.FAILED, "", messageType) + def missingReceiverMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timestamp, null, hashCode, PartnerMetadataStatus.PENDING, null, messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) + def expectedMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timestamp, null, hashCode, PartnerMetadataStatus.FAILED, "", messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) mockClient.getRsToken() >> bearerToken mockClient.requestHistoryEndpoint(sentSubmissionId, bearerToken) >> rsHistoryApiResponse @@ -369,8 +371,8 @@ class PartnerMetadataOrchestratorTest extends Specification { def bearerToken = "token" def rsHistoryApiResponse = "whatever" def messageType = PartnerMetadataMessageType.RESULT - def missingReceiverMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timestamp, timeDelivered, hashCode, PartnerMetadataStatus.PENDING, null, messageType) - def expectedMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timestamp, timeDelivered, hashCode, PartnerMetadataStatus.DELIVERED, null, messageType) + def missingReceiverMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timestamp, timeDelivered, hashCode, PartnerMetadataStatus.PENDING, null, messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) + def expectedMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timestamp, timeDelivered, hashCode, PartnerMetadataStatus.DELIVERED, null, messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) mockClient.getRsToken() >> bearerToken mockClient.requestHistoryEndpoint(sentSubmissionId, bearerToken) >> rsHistoryApiResponse @@ -400,9 +402,7 @@ class PartnerMetadataOrchestratorTest extends Specification { def "setMetadataStatusToFailed sets status to Failed"() { given: def submissionId = "13425" - def metadataStatus = PartnerMetadataStatus.FAILED - def messageType = PartnerMetadataMessageType.RESULT - def optional = Optional.of(new PartnerMetadata("","","","",Instant.now(),null, "",PartnerMetadataStatus.PENDING, "Bad Message", messageType)) + def optional = Optional.of(new PartnerMetadata("","","","",Instant.now(),null, "",PartnerMetadataStatus.PENDING, "Bad Message", PartnerMetadataMessageType.RESULT, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber)) mockPartnerMetadataStorage.readMetadata(submissionId) >> optional when: @@ -410,16 +410,14 @@ class PartnerMetadataOrchestratorTest extends Specification { then: 1 * mockPartnerMetadataStorage.saveMetadata(_ as PartnerMetadata) >> { PartnerMetadata partnerMetadata -> - assert partnerMetadata.deliveryStatus() == metadataStatus + assert partnerMetadata.deliveryStatus() == PartnerMetadataStatus.FAILED } } def "setMetadataStatusToFailed doesn't update status if status is the same"() { given: def submissionId = "13425" - def metadataStatus = PartnerMetadataStatus.FAILED - def messageType = PartnerMetadataMessageType.RESULT - def optional = Optional.of(new PartnerMetadata("","","","",Instant.now(), null, "",metadataStatus, null, messageType)) + def optional = Optional.of(new PartnerMetadata("","","","",Instant.now(), null, "", PartnerMetadataStatus.FAILED, null, PartnerMetadataMessageType.RESULT, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber)) mockPartnerMetadataStorage.readMetadata(submissionId) >> optional when: @@ -596,9 +594,8 @@ class PartnerMetadataOrchestratorTest extends Specification { def senderName = "sender_name" def failure = "This thing is bonked" def status = PartnerMetadataStatus.PENDING - def messageType = PartnerMetadataMessageType.RESULT def mockMetadata = [ - new PartnerMetadata("123456789", null, senderName, "receiver_name", Instant.now(), null, null, status, failure, messageType) + new PartnerMetadata("123456789", null, senderName, "receiver_name", Instant.now(), null, null, status, failure, PartnerMetadataMessageType.RESULT, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) ] mockPartnerMetadataStorage.readMetadataForSender(senderName) >> mockMetadata diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataTest.groovy index 33d34f2e8..8724be8e6 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/metadata/partner/PartnerMetadataTest.groovy @@ -1,9 +1,7 @@ package gov.hhs.cdc.trustedintermediary.etor.metadata.partner - import gov.hhs.cdc.trustedintermediary.PojoTestUtils -import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadata -import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataStatus +import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType import java.time.Instant import spock.lang.Specification @@ -29,10 +27,13 @@ class PartnerMetadataTest extends Specification { def status = PartnerMetadataStatus.DELIVERED def failureReason = "failure reason" def messageType = PartnerMetadataMessageType.RESULT - + def sendingAppDetails = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacilityDetails = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingAppDetails = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacilityDetails = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") when: - def metadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timeReceived, timeDelivered, hash, PartnerMetadataStatus.DELIVERED, failureReason, messageType) + def metadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timeReceived, timeDelivered, hash, PartnerMetadataStatus.DELIVERED, failureReason, messageType, sendingAppDetails, sendingFacilityDetails, receivingAppDetails, receivingFacilityDetails, "placer_order_number") then: metadata.receivedSubmissionId() == receivedSubmissionId @@ -44,6 +45,10 @@ class PartnerMetadataTest extends Specification { metadata.hash() == hash metadata.deliveryStatus() == status metadata.failureReason() == failureReason + metadata.sendingApplicationDetails() == sendingAppDetails + metadata.sendingFacilityDetails() == sendingFacilityDetails + metadata.receivingApplicationDetails() == receivingAppDetails + metadata.receivingFacilityDetails() == receivingFacilityDetails } def "test overloaded constructor"() { @@ -54,9 +59,13 @@ class PartnerMetadataTest extends Specification { def timeDelivered = Instant.now() def hash = "abcd" def status = PartnerMetadataStatus.DELIVERED + def sendingAppDetails = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacilityDetails = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingAppDetails = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacilityDetails = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") when: - def metadata = new PartnerMetadata(receivedSubmissionId, sender, timeReceived, timeDelivered, hash, PartnerMetadataStatus.DELIVERED, PartnerMetadataMessageType.ORDER) + def metadata = new PartnerMetadata(receivedSubmissionId, sender, timeReceived, timeDelivered, hash, PartnerMetadataStatus.DELIVERED, PartnerMetadataMessageType.ORDER, sendingAppDetails, sendingFacilityDetails, receivingAppDetails, receivingFacilityDetails, "placer_order_number") then: metadata.receivedSubmissionId() == receivedSubmissionId @@ -67,26 +76,10 @@ class PartnerMetadataTest extends Specification { metadata.timeDelivered() == timeDelivered metadata.hash() == hash metadata.deliveryStatus() == status - } - - def "test constructor with only received submission ID and hash"() { - given: - def receivedSubmissionId = "receivedSubmissionId" - def hash = "abcd" - - when: - def metadata = new PartnerMetadata(receivedSubmissionId, hash) - - then: - metadata.receivedSubmissionId() == receivedSubmissionId - metadata.sentSubmissionId() == null - metadata.sender() == null - metadata.receiver() == null - metadata.timeReceived() == null - metadata.timeDelivered() == null - metadata.hash() == hash - //Status should default to PENDING - metadata.deliveryStatus() == PartnerMetadataStatus.PENDING + metadata.sendingApplicationDetails() == sendingAppDetails + metadata.sendingFacilityDetails() == sendingFacilityDetails + metadata.receivingApplicationDetails() == receivingAppDetails + metadata.receivingFacilityDetails() == receivingFacilityDetails } def "test constructor with only received submission ID and status"() { @@ -119,7 +112,12 @@ class PartnerMetadataTest extends Specification { def hash = "abcd" def status = PartnerMetadataStatus.DELIVERED def failureReason = "DogCow goes boom" - def metadata = new PartnerMetadata(receivedSubmissionId, null, sender, null, timeReceived, null, hash, status, failureReason, messageType) + def sendingAppDetails = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacilityDetails = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingAppDetails = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacilityDetails = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + + def metadata = new PartnerMetadata(receivedSubmissionId, null, sender, null, timeReceived, null, hash, status, failureReason, messageType, sendingAppDetails, sendingFacilityDetails, receivingAppDetails, receivingFacilityDetails, "placer_order_number") when: def updatedMetadata = metadata.withSentSubmissionId(sentSubmissionId).withReceiver(receiver) @@ -132,6 +130,10 @@ class PartnerMetadataTest extends Specification { updatedMetadata.timeReceived() == timeReceived updatedMetadata.hash() == hash updatedMetadata.deliveryStatus() == status + updatedMetadata.sendingApplicationDetails() == sendingAppDetails + updatedMetadata.sendingFacilityDetails() == sendingFacilityDetails + updatedMetadata.receivingApplicationDetails() == receivingAppDetails + updatedMetadata.receivingFacilityDetails() == receivingFacilityDetails } def "test withDeliveryStatus to update PartnerMetadata"() { @@ -145,7 +147,11 @@ class PartnerMetadataTest extends Specification { def messageType = PartnerMetadataMessageType.RESULT def hash = "abcd" def failureReason = "DogCow goes boom" - def metadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timeReceived, timeDelivered, hash, PartnerMetadataStatus.PENDING, failureReason, messageType) + def sendingAppDetails = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacilityDetails = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingAppDetails = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacilityDetails = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + def metadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timeReceived, timeDelivered, hash, PartnerMetadataStatus.PENDING, failureReason, messageType, sendingAppDetails, sendingFacilityDetails, receivingAppDetails, receivingFacilityDetails, "placer_order_number") when: def newStatus = PartnerMetadataStatus.DELIVERED @@ -161,6 +167,10 @@ class PartnerMetadataTest extends Specification { updatedMetadata.hash() == hash updatedMetadata.deliveryStatus() == newStatus updatedMetadata.failureReason() == failureReason + updatedMetadata.sendingApplicationDetails() == sendingAppDetails + updatedMetadata.sendingFacilityDetails() == sendingFacilityDetails + updatedMetadata.receivingApplicationDetails() == receivingAppDetails + updatedMetadata.receivingFacilityDetails() == receivingFacilityDetails } def "test withTimeDelivered to update PartnerMetadata"() { @@ -174,7 +184,11 @@ class PartnerMetadataTest extends Specification { def messageType = PartnerMetadataMessageType.RESULT def hash = "abcd" def failureReason = "DogCow goes boom" - def metadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timeReceived, null, hash, PartnerMetadataStatus.PENDING, failureReason, messageType) + def sendingAppDetails = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacilityDetails = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingAppDetails = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacilityDetails = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + def metadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, sender, receiver, timeReceived, null, hash, PartnerMetadataStatus.PENDING, failureReason, messageType, sendingAppDetails, sendingFacilityDetails, receivingAppDetails, receivingFacilityDetails, "placer_order_number") when: def updatedMetadata = metadata.withTimeDelivered(timeDelivered) @@ -188,5 +202,9 @@ class PartnerMetadataTest extends Specification { updatedMetadata.timeDelivered() == timeDelivered updatedMetadata.hash() == hash updatedMetadata.failureReason() == failureReason + updatedMetadata.sendingApplicationDetails() == sendingAppDetails + updatedMetadata.sendingFacilityDetails() == sendingFacilityDetails + updatedMetadata.receivingApplicationDetails() == receivingAppDetails + updatedMetadata.receivingFacilityDetails() == receivingFacilityDetails } } diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/orders/SendOrderUseCaseTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/orders/SendOrderUseCaseTest.groovy index 28a77cfb9..d6c3c98f9 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/orders/SendOrderUseCaseTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/orders/SendOrderUseCaseTest.groovy @@ -54,7 +54,15 @@ class SendOrderUseCaseTest extends Specification { 1 * sendOrder.metadata.put(_, EtorMetadataStep.ORDER_CONVERTED_TO_OML) 1 * sendOrder.metadata.put(_, EtorMetadataStep.CONTACT_SECTION_ADDED_TO_PATIENT) 1 * sendOrder.metadata.put(_, EtorMetadataStep.ETOR_PROCESSING_TAG_ADDED_TO_MESSAGE_HEADER) - 1 * mockOrchestrator.updateMetadataForReceivedMessage(receivedSubmissionId, _ as String, messageType) + 1 * mockOrchestrator.updateMetadataForReceivedMessage( + receivedSubmissionId, + _ as String, + messageType, + mockOrder.getSendingApplicationDetails(), + mockOrder.getSendingFacilityDetails(), + mockOrder.getReceivingApplicationDetails(), + mockOrder.getReceivingFacilityDetails(), + mockOrder.getPlacerOrderNumber()) 1 * mockOrchestrator.updateMetadataForSentMessage(receivedSubmissionId, sentSubmissionId) } @@ -89,7 +97,12 @@ class SendOrderUseCaseTest extends Specification { def omlOrder = Mock(Order) def receivedSubmissionId = "receivedId" def messageType = PartnerMetadataMessageType.ORDER - mockOrchestrator.updateMetadataForReceivedMessage(receivedSubmissionId, _ as String, messageType) >> { throw new PartnerMetadataException("Error") } + mockOrchestrator.updateMetadataForReceivedMessage(receivedSubmissionId, _ as String, messageType, + order.getSendingApplicationDetails(), + order.getSendingFacilityDetails(), + order.getReceivingApplicationDetails(), + order.getReceivingFacilityDetails(), + order.getPlacerOrderNumber()) >> { throw new PartnerMetadataException("Error") } TestApplicationContext.injectRegisteredImplementations() when: diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/results/SendResultUseCaseTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/results/SendResultUseCaseTest.groovy index 0e7430aff..7a32b7846 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/results/SendResultUseCaseTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/results/SendResultUseCaseTest.groovy @@ -62,7 +62,12 @@ class SendResultUseCaseTest extends Specification { def result = Mock(Result) def receivedSubmissionId = "receivedId" def messageType = PartnerMetadataMessageType.RESULT - mockOrchestrator.updateMetadataForReceivedMessage(receivedSubmissionId, _ as String, messageType) >> { throw new PartnerMetadataException("Error") } + mockOrchestrator.updateMetadataForReceivedMessage(receivedSubmissionId, _ as String, messageType, + result.getSendingApplicationDetails(), + result.getSendingFacilityDetails(), + result.getReceivingApplicationDetails(), + result.getReceivingFacilityDetails(), + result.getPlacerOrderNumber()) >> { throw new PartnerMetadataException("Error") } TestApplicationContext.injectRegisteredImplementations() when: diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/database/DatabasePartnerMetadataStorageTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/database/DatabasePartnerMetadataStorageTest.groovy index bf008ea90..6b8920304 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/database/DatabasePartnerMetadataStorageTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/database/DatabasePartnerMetadataStorageTest.groovy @@ -1,11 +1,16 @@ package gov.hhs.cdc.trustedintermediary.external.database +import com.fasterxml.jackson.databind.ObjectMapper import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext +import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadata import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataException import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataMessageType -import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataStorage import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataStatus +import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataStorage +import gov.hhs.cdc.trustedintermediary.external.jackson.Jackson +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.Formatter +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.FormatterProcessingException import spock.lang.Specification import java.sql.SQLException @@ -16,25 +21,20 @@ import java.time.Instant class DatabasePartnerMetadataStorageTest extends Specification { private def mockDao + private def mockFormatter - def mockMetadata = new PartnerMetadata( - "receivedSubmissionId", - "sentSubmissionId", - "sender", - "receiver", - Instant.now(), - Instant.now(), - "hash", - PartnerMetadataStatus.PENDING, - "DogCow failure", - PartnerMetadataMessageType.RESULT - ) + def sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + def mockMetadata = new PartnerMetadata("receivedSubmissionId", "sentSubmissionId","sender", "receiver", Instant.now(), Instant.now(), "hash", PartnerMetadataStatus.DELIVERED, "failure reason", PartnerMetadataMessageType.ORDER, sendingApp, sendingFacility, receivingApp, receivingFacility, "placer_order_number") def setup() { TestApplicationContext.reset() TestApplicationContext.init() mockDao = Mock(DbDao) + mockFormatter = Mock(Formatter) TestApplicationContext.register(DbDao, mockDao) TestApplicationContext.register(PartnerMetadataStorage, DatabasePartnerMetadataStorage.getInstance()) @@ -65,8 +65,64 @@ class DatabasePartnerMetadataStorageTest extends Specification { thrown(PartnerMetadataException) } + def "readMetadata unhappy path triggers FormatterProcessingException"() { + given: + def receivedSubmissionId = "receivedSubmissionId" + mockDao.fetchMetadata(_ as String) >> { throw new FormatterProcessingException("Format error", new Throwable()) } + + when: + DatabasePartnerMetadataStorage.getInstance().readMetadata(receivedSubmissionId) + + then: + thrown(PartnerMetadataException) + } + + def "readMetadataForSender unhappy path triggers SQLException"() { + given: + def sender = "testSender" + mockDao.fetchMetadataForSender(sender) >> { throw new SQLException("Database error has occur") } + + when: + DatabasePartnerMetadataStorage.getInstance().readMetadataForSender(sender) + + then: + thrown(PartnerMetadataException) + } + + def "readMetadataForSender unhappy path triggers FormatterProcessingException"() { + given: + def sender = "testSender" + mockDao.fetchMetadataForSender(sender) >> { throw new FormatterProcessingException("Format error", new Throwable()) } + + when: + DatabasePartnerMetadataStorage.getInstance().readMetadataForSender(sender) + + then: + thrown(PartnerMetadataException) + } + + def "readMetadataForSender happy path works"() { + given: + def sender = "testSender" + def metadata1 = mockMetadata + def metadata2 = mockMetadata + def expectedMetadataSet = new HashSet<>() + expectedMetadataSet.add(metadata1) + expectedMetadataSet.add(metadata2) + + mockDao.fetchMetadataForSender(sender) >> expectedMetadataSet + + when: + def actualMetadataSet = DatabasePartnerMetadataStorage.getInstance().readMetadataForSender(sender) + + then: + actualMetadataSet.size() == expectedMetadataSet.size() + actualMetadataSet.containsAll(expectedMetadataSet) + } + def "saveMetadata happy path works"() { given: + def testMapper = new ObjectMapper() List columns = List.of( new DbColumn("received_message_id", mockMetadata.receivedSubmissionId(), false, Types.VARCHAR), @@ -78,8 +134,15 @@ class DatabasePartnerMetadataStorageTest extends Specification { new DbColumn("time_delivered", Timestamp.from(mockMetadata.timeDelivered()),true, Types.TIMESTAMP), new DbColumn("delivery_status", mockMetadata.deliveryStatus().toString(),true,Types.OTHER), new DbColumn("failure_reason", mockMetadata.failureReason(), true, Types.VARCHAR), - new DbColumn("message_type", mockMetadata.messageType().toString(), false, Types.OTHER) + new DbColumn("message_type", mockMetadata.messageType().toString(), false, Types.OTHER), + new DbColumn("placer_order_number", mockMetadata.placerOrderNumber(), false, Types.VARCHAR), + new DbColumn("sending_application_details", testMapper.writeValueAsString(mockMetadata.sendingApplicationDetails()), false, Types.OTHER), + new DbColumn("sending_facility_details", testMapper.writeValueAsString(mockMetadata.sendingFacilityDetails()), false, Types.OTHER), + new DbColumn("receiving_application_details", testMapper.writeValueAsString(mockMetadata.receivingApplicationDetails()), false, Types.OTHER), + new DbColumn("receiving_facility_details", testMapper.writeValueAsString(mockMetadata.receivingFacilityDetails()), false, Types.OTHER) ) + TestApplicationContext.register(Formatter, Jackson.getInstance()) + TestApplicationContext.injectRegisteredImplementations() when: DatabasePartnerMetadataStorage.getInstance().saveMetadata(mockMetadata) @@ -91,6 +154,64 @@ class DatabasePartnerMetadataStorageTest extends Specification { def "saveMetadata unhappy path works"() { given: mockDao.upsertData(_ as String, _ as List, _ as String) >> { throw new SQLException("Something went wrong!") } + TestApplicationContext.register(Formatter, Jackson.getInstance()) + TestApplicationContext.injectRegisteredImplementations() + + when: + DatabasePartnerMetadataStorage.getInstance().saveMetadata(mockMetadata) + + then: + thrown(PartnerMetadataException) + } + + def "saveMetadata unhappy path first format call triggers FormatterProcessingException"() { + given: + mockFormatter.convertToJsonString(_ as MessageHdDataType) >> { throw new FormatterProcessingException('error', new Throwable()) } + + TestApplicationContext.register(Formatter, mockFormatter) + TestApplicationContext.injectRegisteredImplementations() + + when: + DatabasePartnerMetadataStorage.getInstance().saveMetadata(mockMetadata) + + then: + thrown(PartnerMetadataException) + } + + def "saveMetadata second unhappy path format call triggers FormatterProcessingException"() { + given: + mockFormatter.convertToJsonString(_ as MessageHdDataType) >> "ok" >> { throw new FormatterProcessingException('error', new Throwable()) } + + TestApplicationContext.register(Formatter, mockFormatter) + TestApplicationContext.injectRegisteredImplementations() + + when: + DatabasePartnerMetadataStorage.getInstance().saveMetadata(mockMetadata) + + then: + thrown(PartnerMetadataException) + } + + def "saveMetadata third unhappy path format call triggers FormatterProcessingException"() { + given: + mockFormatter.convertToJsonString(_ as MessageHdDataType) >> ["ok", "ok"] >> { throw new FormatterProcessingException('error', new Throwable()) } + + TestApplicationContext.register(Formatter, mockFormatter) + TestApplicationContext.injectRegisteredImplementations() + + when: + DatabasePartnerMetadataStorage.getInstance().saveMetadata(mockMetadata) + + then: + thrown(PartnerMetadataException) + } + + def "saveMetadata fourth unhappy path format call triggers FormatterProcessingException"() { + given: + mockFormatter.convertToJsonString(_ as MessageHdDataType) >> ["ok", "ok" , "ok"] >> { throw new FormatterProcessingException('error', new Throwable()) } + + TestApplicationContext.register(Formatter, mockFormatter) + TestApplicationContext.injectRegisteredImplementations() when: DatabasePartnerMetadataStorage.getInstance().saveMetadata(mockMetadata) @@ -101,6 +222,7 @@ class DatabasePartnerMetadataStorageTest extends Specification { def "saveMetadata writes null timestamp"() { given: + def testMapper = new ObjectMapper() def mockMetadata = new PartnerMetadata( "receivedSubmissionId", "sentSubmissionId", @@ -111,7 +233,12 @@ class DatabasePartnerMetadataStorageTest extends Specification { "hash", null, // PartnerMetadata defaults deliveryStatus to PENDING on null, so that's why we're asserting not-null bellow "DogCow failure", - null + null, + sendingApp, + sendingFacility, + receivingApp, + receivingFacility, + "placer_order_number" ) List columns = @@ -125,8 +252,15 @@ class DatabasePartnerMetadataStorageTest extends Specification { new DbColumn("time_delivered", null,true, Types.TIMESTAMP), new DbColumn("delivery_status", mockMetadata.deliveryStatus().toString(), true,Types.OTHER), new DbColumn("failure_reason", mockMetadata.failureReason(), true, Types.VARCHAR), - new DbColumn("message_type", null, false, Types.OTHER) + new DbColumn("message_type", null, false, Types.OTHER), + new DbColumn("placer_order_number", mockMetadata.placerOrderNumber(), false, Types.VARCHAR), + new DbColumn("sending_application_details", testMapper.writeValueAsString(mockMetadata.sendingApplicationDetails()), false, Types.OTHER), + new DbColumn("sending_facility_details", testMapper.writeValueAsString(mockMetadata.sendingFacilityDetails()), false, Types.OTHER), + new DbColumn("receiving_application_details", testMapper.writeValueAsString(mockMetadata.receivingApplicationDetails()), false, Types.OTHER), + new DbColumn("receiving_facility_details", testMapper.writeValueAsString(mockMetadata.receivingFacilityDetails()), false, Types.OTHER) ) + TestApplicationContext.register(Formatter, Jackson.getInstance()) + TestApplicationContext.injectRegisteredImplementations() when: DatabasePartnerMetadataStorage.getInstance().saveMetadata(mockMetadata) diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/database/PostgresDaoTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/database/PostgresDaoTest.groovy index 35b18e3ab..f517608b1 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/database/PostgresDaoTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/database/PostgresDaoTest.groovy @@ -1,11 +1,19 @@ package gov.hhs.cdc.trustedintermediary.external.database +import com.fasterxml.jackson.databind.ObjectMapper import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext +import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadata import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataMessageType import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataStatus +import gov.hhs.cdc.trustedintermediary.external.jackson.Jackson import gov.hhs.cdc.trustedintermediary.wrappers.database.ConnectionPool import gov.hhs.cdc.trustedintermediary.wrappers.database.DatabaseCredentialsProvider +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.Formatter +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.FormatterProcessingException +import gov.hhs.cdc.trustedintermediary.wrappers.formatter.TypeReference +import spock.lang.Specification + import java.sql.Connection import java.sql.PreparedStatement import java.sql.ResultSet @@ -13,14 +21,19 @@ import java.sql.SQLException import java.sql.Timestamp import java.sql.Types import java.time.Instant -import spock.lang.Specification class PostgresDaoTest extends Specification { - private ConnectionPool mockConnPool private Connection mockConn private PreparedStatement mockPreparedStatement private ResultSet mockResultSet + private Formatter mockFormatter + private ObjectMapper testMapper + + private sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + private sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + private receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + private receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") def setup() { TestApplicationContext.reset() @@ -30,11 +43,20 @@ class PostgresDaoTest extends Specification { mockConn = Mock(Connection) mockPreparedStatement = Mock(PreparedStatement) mockResultSet = Mock(ResultSet) + mockFormatter = Mock(Formatter) + + testMapper = new ObjectMapper() + mockResultSet.getString("sending_application_details") >> testMapper.writeValueAsString(sendingApp) + mockResultSet.getString("sending_facility_details") >> testMapper.writeValueAsString(sendingFacility) + mockResultSet.getString("receiving_application_details") >> testMapper.writeValueAsString(receivingApp) + mockResultSet.getString("receiving_facility_details") >> testMapper.writeValueAsString(receivingFacility) + def mockCredentialsProvider = Mock(DatabaseCredentialsProvider) mockCredentialsProvider.getPassword() >> "DogCow password" TestApplicationContext.register(DatabaseCredentialsProvider, mockCredentialsProvider) TestApplicationContext.register(PostgresDao, PostgresDao.getInstance()) + TestApplicationContext.register(Formatter, mockFormatter) } def "upsertData works"() { @@ -46,6 +68,10 @@ class PostgresDaoTest extends Specification { new DbColumn("third_column", Timestamp.from(Instant.now()), false, Types.TIMESTAMP_WITH_TIMEZONE), new DbColumn("second_column_with_upsert_overwrite", Timestamp.from(Instant.now()), true, Types.TIMESTAMP_WITH_TIMEZONE), new DbColumn("fourth_column_null", null, false, Types.VARCHAR), + new DbColumn("sending_application_details", sendingApp, false, Types.OTHER), + new DbColumn("sending_facility_details", sendingFacility, false, Types.OTHER), + new DbColumn("receiving_application_details", receivingApp, false, Types.OTHER), + new DbColumn("receiving_facility_details", receivingFacility, false, Types.OTHER), ] def conflictColumnName = pkColumnName @@ -97,6 +123,10 @@ class PostgresDaoTest extends Specification { def columns = [ new DbColumn("Moof", "Clarus", false, Types.VARCHAR), new DbColumn("second_column_with_upsert_overwrite", Timestamp.from(Instant.now()), false, Types.TIMESTAMP_WITH_TIMEZONE), + new DbColumn("sending_application_details", sendingApp, false, Types.OTHER), + new DbColumn("sending_facility_details", sendingFacility, false, Types.OTHER), + new DbColumn("receiving_application_details", receivingApp, false, Types.OTHER), + new DbColumn("receiving_facility_details", receivingFacility, false, Types.OTHER), ] mockConnPool.getConnection() >> mockConn @@ -116,7 +146,7 @@ class PostgresDaoTest extends Specification { return mockPreparedStatement } - columns.size() * mockPreparedStatement.setObject(_ as Integer, _, _ as Integer) + 6 * mockPreparedStatement.setObject(_ as Integer, _, _ as Integer) 1 * mockPreparedStatement.executeUpdate() } @@ -130,7 +160,11 @@ class PostgresDaoTest extends Specification { when: PostgresDao.getInstance().upsertData("DogCow", [ - new DbColumn("", "", false, Types.VARCHAR) + new DbColumn("", "", false, Types.VARCHAR), + new DbColumn("sending_application_details", sendingApp, false, Types.OTHER), + new DbColumn("sending_facility_details", sendingFacility, false, Types.OTHER), + new DbColumn("receiving_application_details", receivingApp, false, Types.OTHER), + new DbColumn("receiving_facility_details", receivingFacility, false, Types.OTHER), ], null) then: @@ -146,7 +180,9 @@ class PostgresDaoTest extends Specification { mockResultSet.getTimestamp(_ as String) >> Timestamp.from(Instant.now()) mockResultSet.getString("delivery_status") >> "DELIVERED" mockResultSet.getString("message_type") >> "RESULT" + mockResultSet.getString("placer_order_number") >> "placer_order_number" TestApplicationContext.register(ConnectionPool, mockConnPool) + TestApplicationContext.register(Formatter, Jackson.getInstance()) TestApplicationContext.injectRegisteredImplementations() when: @@ -202,7 +238,8 @@ class PostgresDaoTest extends Specification { def status = PartnerMetadataStatus.PENDING def reason = "It done Goofed" def messageType = PartnerMetadataMessageType.RESULT - def expected = new PartnerMetadata(receivedMessageId, sentMessageId, sender, receiver, timeReceived, timeDelivered, hash, status, reason, messageType) + def placerOrderNumber = "placer_order_number" + def expected = new PartnerMetadata(receivedMessageId, sentMessageId, sender, receiver, timeReceived, timeDelivered, hash, status, reason, messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, placerOrderNumber) mockConnPool.getConnection() >> mockConn mockConn.prepareStatement(_ as String) >> mockPreparedStatement @@ -217,9 +254,11 @@ class PostgresDaoTest extends Specification { mockResultSet.getString("delivery_status") >> status.toString() mockResultSet.getString("failure_reason") >> reason mockResultSet.getString("message_type") >> messageType.toString() + mockResultSet.getString("placer_order_number") >> placerOrderNumber mockPreparedStatement.executeQuery() >> mockResultSet TestApplicationContext.register(ConnectionPool, mockConnPool) + TestApplicationContext.register(Formatter, Jackson.getInstance()) TestApplicationContext.injectRegisteredImplementations() when: @@ -239,7 +278,9 @@ class PostgresDaoTest extends Specification { mockResultSet.getString("delivery_status") >> "DELIVERED" mockResultSet.getString("message_type") >> "RESULT" mockResultSet.getString("failure_reason") >> "Your time is up" + mockResultSet.getString("placer_order_number") >> "TEST" TestApplicationContext.register(ConnectionPool, mockConnPool) + TestApplicationContext.register(Formatter, Jackson.getInstance()) TestApplicationContext.injectRegisteredImplementations() when: @@ -253,8 +294,14 @@ class PostgresDaoTest extends Specification { given: def sender = "DogCow" def messageType = PartnerMetadataMessageType.RESULT - def expected1 = new PartnerMetadata("12345", "7890", sender, "You'll get your just reward", Instant.parse("2024-01-03T15:45:33.30Z"),Instant.parse("2024-01-03T15:45:33.30Z"), sender.hashCode().toString(), PartnerMetadataStatus.PENDING, "It done Goofed", messageType) - def expected2 = new PartnerMetadata("doreyme", "fasole", sender, "receiver", Instant.now(), Instant.now(), "gobeltygoook", PartnerMetadataStatus.DELIVERED, "cause I said so", messageType) + def expected1 = new PartnerMetadata("12345", "7890", sender, "You'll get your just reward", + Instant.parse("2024-01-03T15:45:33.30Z"), Instant.parse("2024-01-03T15:45:33.30Z"), sender.hashCode().toString(), + PartnerMetadataStatus.PENDING, "It done Goofed", messageType, sendingApp, sendingFacility, + receivingApp, receivingFacility, "placer_order_number") + def expected2 = new PartnerMetadata("doreyme", "fasole", sender, "receiver", + Instant.now(), Instant.now(), "gobeltygoook", + PartnerMetadataStatus.DELIVERED, "cause I said so", messageType, sendingApp, sendingFacility, + receivingApp, receivingFacility, "placer_order_number") mockConnPool.getConnection() >> mockConn mockConn.prepareStatement(_ as String) >> mockPreparedStatement @@ -299,16 +346,60 @@ class PostgresDaoTest extends Specification { expected1.messageType().toString(), expected2.messageType().toString() ] + mockResultSet.getString("sending_application_details") >>> [ + testMapper.writeValueAsString(sendingApp), + testMapper.writeValueAsString(sendingApp) + ] + mockResultSet.getString("sending_facility_details") >>> [ + testMapper.writeValueAsString(sendingFacility), + testMapper.writeValueAsString(sendingFacility), + ] + mockResultSet.getString("receiving_application_details") >>> [ + testMapper.writeValueAsString(receivingApp), + testMapper.writeValueAsString(receivingApp) + ] + mockResultSet.getString("receiving_facility_details") >>> [ + testMapper.writeValueAsString(receivingFacility), + testMapper.writeValueAsString(receivingFacility) + ] + mockResultSet.getString("placer_order_number") >>> [ + expected1.placerOrderNumber(), + expected2.placerOrderNumber() + ] mockPreparedStatement.executeQuery() >> mockResultSet TestApplicationContext.register(ConnectionPool, mockConnPool) + TestApplicationContext.register(Formatter, Jackson.getInstance()) TestApplicationContext.injectRegisteredImplementations() - when: def actual = PostgresDao.getInstance().fetchMetadataForSender("sender") then: actual.containsAll(Set.of(expected1, expected2)) } + + def "fetchMetadata throws exception for FormatterProcessingException"() { + given: + mockConnPool.getConnection() >> mockConn + mockConn.prepareStatement(_ as String) >> mockPreparedStatement + mockPreparedStatement.executeQuery() >> mockResultSet + mockResultSet.next() >> true + mockResultSet.getTimestamp("time_received") >> null + mockResultSet.getString("delivery_status") >> "DELIVERED" + mockResultSet.getString("message_type") >> "RESULT" + mockResultSet.getString("failure_reason") >> "Your time is up" + mockResultSet.getString("placer_order_number") >> "TEST" + mockFormatter.convertJsonToObject(_ as String, _ as TypeReference) >> { throw new FormatterProcessingException('error', new Throwable()) } + + TestApplicationContext.register(ConnectionPool, mockConnPool) + TestApplicationContext.register(Formatter, mockFormatter) + TestApplicationContext.injectRegisteredImplementations() + + when: + PostgresDao.getInstance().fetchMetadata("mock_lookup") + + then: + thrown(FormatterProcessingException) + } } diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/hapi/HapiMetadataConverterTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/hapi/HapiMetadataConverterTest.groovy index 937ef38eb..f27d6eb8e 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/hapi/HapiMetadataConverterTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/hapi/HapiMetadataConverterTest.groovy @@ -1,5 +1,6 @@ package gov.hhs.cdc.trustedintermediary.external.hapi +import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadata import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataMessageType import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataStatus @@ -28,8 +29,12 @@ class HapiMetadataConverterTest extends Specification { def hash = "hash" def failureReason = "timed_out" def messageType = PartnerMetadataMessageType.ORDER + def sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") PartnerMetadata metadata = new PartnerMetadata( - "receivedSubmissionId", "sentSubmissionId", sender, receiver, time, time, hash, PartnerMetadataStatus.DELIVERED, failureReason, messageType) + "receivedSubmissionId", "sentSubmissionId", sender, receiver, time, time, hash, PartnerMetadataStatus.DELIVERED, failureReason, messageType, sendingApp, sendingFacility, receivingApp, receivingFacility, "placer_order_number") when: def result = HapiPartnerMetadataConverter.getInstance().extractPublicMetadataToOperationOutcome(metadata, "receivedSubmissionId").getUnderlyingOutcome() as OperationOutcome diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/localfile/FilePartnerMetadataStorageTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/localfile/FilePartnerMetadataStorageTest.groovy index c3802e503..11697c239 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/localfile/FilePartnerMetadataStorageTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/localfile/FilePartnerMetadataStorageTest.groovy @@ -1,6 +1,7 @@ package gov.hhs.cdc.trustedintermediary.external.localfile import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext +import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadata import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataException import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataMessageType @@ -27,7 +28,11 @@ class FilePartnerMetadataStorageTest extends Specification { given: def expectedReceivedSubmissionId = "receivedSubmissionId" def expectedSentSubmissionId = "receivedSubmissionId" - PartnerMetadata metadata = new PartnerMetadata(expectedReceivedSubmissionId, expectedSentSubmissionId, "sender", "receiver", Instant.parse("2023-12-04T18:51:48.941875Z"),Instant.parse("2023-12-04T18:51:48.941875Z"), "abcd", PartnerMetadataStatus.DELIVERED, null, PartnerMetadataMessageType.ORDER) + def sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + PartnerMetadata metadata = new PartnerMetadata(expectedReceivedSubmissionId, expectedSentSubmissionId, "sender", "receiver", Instant.parse("2023-12-04T18:51:48.941875Z"),Instant.parse("2023-12-04T18:51:48.941875Z"), "abcd", PartnerMetadataStatus.DELIVERED, null, PartnerMetadataMessageType.ORDER, sendingApp, sendingFacility, receivingApp, receivingFacility, "placer_order_number") TestApplicationContext.register(Formatter, Jackson.getInstance()) TestApplicationContext.injectRegisteredImplementations() @@ -42,7 +47,11 @@ class FilePartnerMetadataStorageTest extends Specification { def "saveMetadata throws PartnerMetadataException when unable to save file"() { given: - PartnerMetadata metadata = new PartnerMetadata("receivedSubmissionId", "sentSubmissionId","sender", "receiver", Instant.now(), Instant.now(), "abcd", PartnerMetadataStatus.DELIVERED, null, PartnerMetadataMessageType.ORDER) + def sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + PartnerMetadata metadata = new PartnerMetadata("receivedSubmissionId", "sentSubmissionId","sender", "receiver", Instant.now(), Instant.now(), "abcd", PartnerMetadataStatus.DELIVERED, null, PartnerMetadataMessageType.ORDER, sendingApp, sendingFacility, receivingApp, receivingFacility, "placer_order_number") def mockFormatter = Mock(Formatter) mockFormatter.convertToJsonString(_ as PartnerMetadata) >> {throw new FormatterProcessingException("error", new Exception())} @@ -66,7 +75,11 @@ class FilePartnerMetadataStorageTest extends Specification { //write something to the hard drive so that the `readMetadata` in the when gets pass the file existence check def submissionId = "asljfaskljgalsjgjlas" - PartnerMetadata metadata = new PartnerMetadata(submissionId, null, null, null, null, null, null, null, null, null) + def sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + PartnerMetadata metadata = new PartnerMetadata(submissionId, null, null, null, null, null, null, null, null, null, sendingApp, sendingFacility, receivingApp, receivingFacility, "placer_order_number") FilePartnerMetadataStorage.getInstance().saveMetadata(metadata) when: @@ -87,8 +100,12 @@ class FilePartnerMetadataStorageTest extends Specification { def "readMetadataForSender returns a set of PartnerMetadata"() { given: def sender = "same_sender" - PartnerMetadata metadata2 = new PartnerMetadata("abcdefghi", null, sender, null, null, null, null, null, null, null) - PartnerMetadata metadata1 = new PartnerMetadata("123456789", null, sender, null, null, null, null, null, null, null) + def sendingApp = new MessageHdDataType("sending_app_name", "sending_app_id", "sending_app_type") + def sendingFacility = new MessageHdDataType("sending_facility_name", "sending_facility_id", "sending_facility_type") + def receivingApp = new MessageHdDataType("receiving_app_name", "receiving_app_id", "receiving_app_type") + def receivingFacility = new MessageHdDataType("receiving_facility_name", "receiving_facility_id", "receiving_facility_type") + PartnerMetadata metadata2 = new PartnerMetadata("abcdefghi", null, sender, null, null, null, null, null, null, null, sendingApp, sendingFacility, receivingApp, receivingFacility, "placer_order_number") + PartnerMetadata metadata1 = new PartnerMetadata("123456789", null, sender, null, null, null, null, null, null, null, sendingApp, sendingFacility, receivingApp, receivingFacility, "placer_order_number") TestApplicationContext.register(Formatter, Jackson.getInstance()) TestApplicationContext.injectRegisteredImplementations()