From cb628706fb2a3baa1fa4ecd1d6ad25f36aa5fbf0 Mon Sep 17 00:00:00 2001 From: rushdynajath Date: Thu, 10 Oct 2024 14:40:52 +0100 Subject: [PATCH 1/8] Merge main into dev (#205) * Bump System.Runtime.Caching in /src/UKHO.ERPFacade.Common (#199) Bumps [System.Runtime.Caching](https://github.com/dotnet/runtime) from 8.0.0 to 8.0.1. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) --- updated-dependencies: - dependency-name: System.Runtime.Caching dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump the all-packages group with 4 updates (#196) * Bump the all-packages group with 4 updates Bumps the all-packages group with 4 updates: [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore), [SoapCore](https://github.com/DigDes/SoapCore), [RestSharp](https://github.com/restsharp/RestSharp) and [WireMock.Net](https://github.com/WireMock-Net/WireMock.Net). Updates `Swashbuckle.AspNetCore` from 6.8.0 to 6.8.1 - [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases) - [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.8.0...v6.8.1) Updates `SoapCore` from 1.1.0.49 to 1.1.0.51 - [Release notes](https://github.com/DigDes/SoapCore/releases) - [Commits](https://github.com/DigDes/SoapCore/compare/v1.1.0.49...v1.1.0.51) Updates `RestSharp` from 112.0.0 to 112.1.0 - [Release notes](https://github.com/restsharp/RestSharp/releases) - [Commits](https://github.com/restsharp/RestSharp/compare/112.0.0...112.1.0) Updates `WireMock.Net` from 1.6.5 to 1.6.6 - [Release notes](https://github.com/WireMock-Net/WireMock.Net/releases) - [Changelog](https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md) - [Commits](https://github.com/WireMock-Net/WireMock.Net/compare/1.6.5...1.6.6) --- updated-dependencies: - dependency-name: Swashbuckle.AspNetCore dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: SoapCore dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: RestSharp dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-packages - dependency-name: WireMock.Net dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages ... Signed-off-by: dependabot[bot] * Add suppression for CVE-2024-43483 in System.Runtime.Caching * Add suppression for CVE-2022-34716 in System.Security.Cryptography.Xml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: HugoBurgess <128484816+HugoBurgess@users.noreply.github.com> Co-authored-by: rushdynajath --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: HugoBurgess <128484816+HugoBurgess@users.noreply.github.com> --- NVDSuppressions.xml | 14 ++++++++++++++ src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj | 2 +- .../UKHO.ERPFacade.Common.csproj | 2 +- .../UKHO.SAP.MockAPIService.csproj | 2 +- .../UKHO.ERPFacade.API.FunctionalTests.csproj | 2 +- .../UKHO.ERPFacade.Common.UnitTests.csproj | 2 +- 6 files changed, 19 insertions(+), 5 deletions(-) diff --git a/NVDSuppressions.xml b/NVDSuppressions.xml index 4d323872..3b988eb9 100644 --- a/NVDSuppressions.xml +++ b/NVDSuppressions.xml @@ -768,4 +768,18 @@ ^pkg:generic/YamlDotNet@.*$ CVE-2018-1000210 + + + ^pkg:nuget/System\.Runtime\.Caching@.*$ + CVE-2024-43483 + + + + ^pkg:nuget/System\.Security\.Cryptography\.Xml@.*$ + CVE-2022-34716 + diff --git a/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj b/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj index a3297d88..2234d2d5 100644 --- a/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj +++ b/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj @@ -48,7 +48,7 @@ - + diff --git a/src/UKHO.ERPFacade.Common/UKHO.ERPFacade.Common.csproj b/src/UKHO.ERPFacade.Common/UKHO.ERPFacade.Common.csproj index 039a2f08..2c660fc1 100644 --- a/src/UKHO.ERPFacade.Common/UKHO.ERPFacade.Common.csproj +++ b/src/UKHO.ERPFacade.Common/UKHO.ERPFacade.Common.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/UKHO.SAP.MockAPIService/UKHO.SAP.MockAPIService.csproj b/src/UKHO.SAP.MockAPIService/UKHO.SAP.MockAPIService.csproj index 947b45e5..06ac77ac 100644 --- a/src/UKHO.SAP.MockAPIService/UKHO.SAP.MockAPIService.csproj +++ b/src/UKHO.SAP.MockAPIService/UKHO.SAP.MockAPIService.csproj @@ -22,7 +22,7 @@ - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj b/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj index 3fc96a1a..939dcc9e 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj @@ -40,7 +40,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/tests/UKHO.ERPFacade.Common.UnitTests/UKHO.ERPFacade.Common.UnitTests.csproj b/tests/UKHO.ERPFacade.Common.UnitTests/UKHO.ERPFacade.Common.UnitTests.csproj index 2134f1d1..049e4a02 100644 --- a/tests/UKHO.ERPFacade.Common.UnitTests/UKHO.ERPFacade.Common.UnitTests.csproj +++ b/tests/UKHO.ERPFacade.Common.UnitTests/UKHO.ERPFacade.Common.UnitTests.csproj @@ -32,7 +32,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 1cf96cfec2b8f4735629cbd0aa15ff71ad0669bc Mon Sep 17 00:00:00 2001 From: Vishal14583 <61726015+Vishal14583@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:57:35 +0100 Subject: [PATCH 2/8] ADDS live issue fix for item tag in xml payload (#209) * issue fix around item tag * Updated item tag in expected XMLs --------- Co-authored-by: Vishal Dukare Co-authored-by: rushikeshkhopatkar --- .../Helpers/EncContentSapMessageBuilder.cs | 2 +- .../ERPFacadeExpectedXmlFiles/2NewCells.xml | Bin 13874 -> 13874 bytes .../3AdditionalCoverageCell.xml | Bin 10286 -> 10286 bytes ...l_AND_CancelCellWithNewCellReplacement.xml | Bin 23812 -> 23812 bytes .../AdditionalCoverageWithNewEdition.xml | Bin 7414 -> 7414 bytes .../CancelCellWithExistingCellReplacement.xml | 28 ++++++------ .../CancelCellWithNewCellReplacement.xml | Bin 22584 -> 22584 bytes ...nt_AND_CellMetadataChange_AND_MoveCell.xml | Bin 25132 -> 25132 bytes ...lWithNewCellReplacement_AND_UpdateCell.xml | Bin 19498 -> 19498 bytes .../CancelCellWithoutCellReplacement.xml | 16 +++---- .../CellMetadataChange.xml | 16 +++---- .../CellMetadataChangeWithNewCell.xml | 8 ++-- .../CellMetadataChange_AND_SuspendCell.xml | 20 ++++----- .../ERPFacadeExpectedXmlFiles/MoveCell.xml | 20 ++++----- .../MoveCell_AND_SuspendCell.xml | 32 +++++++------- .../MultipleCellsInSingleUnit.xml | 40 +++++++++--------- .../ERPFacadeExpectedXmlFiles/NewCell.xml | Bin 7620 -> 7620 bytes ...l_AND_CancelCellWithNewCellReplacement.xml | Bin 21036 -> 21036 bytes .../NewCell_AND_MoveCell.xml | Bin 14900 -> 14900 bytes .../NewCell_AND_UoSMetadataChange.xml | Bin 8996 -> 8996 bytes ..._AND_UpdateCell_AND_CellMetadataChange.xml | Bin 15148 -> 15148 bytes .../ERPFacadeExpectedXmlFiles/Re-issue.xml | 16 +++---- .../ERPFacadeExpectedXmlFiles/SuspendCell.xml | 12 +++--- .../SuspendCell_AND_WithdrawCell.xml | 24 +++++------ .../UoSMetadataChange.xml | 4 +- .../ERPFacadeExpectedXmlFiles/UpdateCell.xml | Bin 5978 -> 5978 bytes .../UpdateCellWithNewEdition.xml | Bin 5978 -> 5978 bytes .../UpdateCellsWithDifferentStatusName.xml | Bin 10654 -> 10654 bytes .../WithdrawCell.xml | 12 +++--- .../Helpers/SAPXmlHelper.cs | 4 +- 30 files changed, 127 insertions(+), 127 deletions(-) diff --git a/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs b/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs index 900e9fa0..892e37ad 100644 --- a/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs +++ b/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs @@ -285,7 +285,7 @@ private XmlElement BuildAction(XmlDocument soapXml, Product product, UnitOfSale DecryptedPermit decryptedPermit = null; // Create main item node - var itemNode = soapXml.CreateElement(nameof(Item)); + var itemNode = soapXml.CreateElement(Item); // Add basic action-related nodes AppendChildNode(itemNode, soapXml, ActionNumber, action.ActionNumber.ToString()); diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/2NewCells.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/2NewCells.xml index 9c174cbf73aaf5dd27ad7906d788c86c7e5e3c6c..75f491d540c26e47e3ac7f67bb735b373ce6ed8e 100644 GIT binary patch delta 153 zcmdm#vngjo91COS=6IINY>b(c<5?7$Z5Tkbb|h<5?7$Z5Tkbs<`0ofhy1tD2FP* U7On&mNMws<`0ofhy1tD2FP* U7On&mNMw014134 UKHO - + 1 REPLACED WITH ENC CELL ENC CELL @@ -30,8 +30,8 @@ N - - + + 2 CHANGE ENC CELL ENC CELL @@ -52,8 +52,8 @@ N - - + + 3 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -74,8 +74,8 @@ N - - + + 4 REMOVE ENC CELL FROM AVCS UNIT OF SALE AVCS UNIT @@ -96,8 +96,8 @@ N - - + + 5 REMOVE ENC CELL FROM AVCS UNIT OF SALE AVCS UNIT @@ -118,8 +118,8 @@ N - - + + 6 CANCEL ENC CELL ENC CELL @@ -140,8 +140,8 @@ N - - + + 7 CANCEL AVCS UNIT OF SALE AVCS UNIT @@ -162,7 +162,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CancelCellWithNewCellReplacement.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CancelCellWithNewCellReplacement.xml index c1211c726d49d58f5a325adb863cb3cf6a7fa189..e28e414bdc9ae7373ca851a6ddff4c54d17d4280 100644 GIT binary patch delta 239 zcmdn7fpNzM#tjK9jG3DgSw6BcW=?)6rwk+$SsXX-;9i6(a6sq@D~bv($!n+rZt_m3 z0`FAN1g2@(psKJiKohuS8U$CdIna74oC9=}^JYIsKe)i=gKpgjPN7dCoC8*B6{G|b QNMwCcSW=@`HsSG3&SsXWS;eNo1BJfMl2`;cXQM?(>0W0^C zwLuklqZEWHutXyPRUk_*4pl(UBner-dGilTG=W3*XaYU1eyCcUywL=H1bCpTSP>?N ODxepm1QG~LybS;}O<3*# delta 273 zcmZ2;gmKLg#tjK9jGmhlS>CcSdQP5bsSG3&SsXWS;eNo1BJfMl2`;cXQM?(>0W0^C zwLuklqZEWHutXyPRUk_*4pl(UBner-dGilTG=W3*XaYU1eyCcUywL=H1bCpTSP>?N ODxepm1QG~LybS;lFI4UT diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CancelCellWithNewCellReplacement_AND_UpdateCell.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CancelCellWithNewCellReplacement_AND_UpdateCell.xml index b556bdf6755c603ab2baf610c1199566a69f567c..f6a412c7c21a3838f47ff92e8c649b6c207a3f70 100644 GIT binary patch delta 235 zcmZ2AgK^ai#tjK9jG3DgS>CcSW=>9IQDnAZ0MU+{w{SmTMHBiZ=!7J+IZ?b8i3`@` zA{&G*^hYTUUFd*D61q@_UJ$wi98CRCRXK0|X61n{w9G*cT}a1G2_hsrd4eFzCcSdQMJcQDnAZ0MU+{w{SmTMHBiZ=!7J+IZ?b8i3`@` zA{&G*^hYTUUFd*D61q@_UJ$wi98CRCRXK0|X61n{w9G*cT}a1G2_hsrd4eFz014725 UKHO - + 1 REMOVE ENC CELL FROM AVCS UNIT OF SALE AVCS UNIT @@ -30,8 +30,8 @@ N - - + + 2 REMOVE ENC CELL FROM AVCS UNIT OF SALE AVCS UNIT @@ -52,8 +52,8 @@ N - - + + 3 CANCEL ENC CELL ENC CELL @@ -74,8 +74,8 @@ N - - + + 4 CANCEL AVCS UNIT OF SALE AVCS UNIT @@ -96,7 +96,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChange.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChange.xml index f53b0ea1..eb857028 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChange.xml +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChange.xml @@ -9,7 +9,7 @@ 014823 UKHO - + 1 CHANGE ENC CELL ENC CELL @@ -30,8 +30,8 @@ N - - + + 2 CHANGE ENC CELL ENC CELL @@ -52,8 +52,8 @@ N - - + + 3 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -74,8 +74,8 @@ N - - + + 4 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -96,7 +96,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChangeWithNewCell.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChangeWithNewCell.xml index bee419fa..eb9dd579 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChangeWithNewCell.xml +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChangeWithNewCell.xml @@ -9,7 +9,7 @@ 015038 UKHO - + 1 CHANGE ENC CELL ENC CELL @@ -30,8 +30,8 @@ N - - + + 2 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -52,7 +52,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChange_AND_SuspendCell.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChange_AND_SuspendCell.xml index 6e0ca8b7..5baca0a5 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChange_AND_SuspendCell.xml +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/CellMetadataChange_AND_SuspendCell.xml @@ -9,7 +9,7 @@ 014929 UKHO - + 1 CHANGE ENC CELL ENC CELL @@ -30,8 +30,8 @@ N - - + + 2 CHANGE ENC CELL ENC CELL @@ -52,8 +52,8 @@ N - - + + 3 CHANGE ENC CELL ENC CELL @@ -74,8 +74,8 @@ N - - + + 4 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -96,8 +96,8 @@ N - - + + 5 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -118,7 +118,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MoveCell.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MoveCell.xml index 209f5e9a..f05d79da 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MoveCell.xml +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MoveCell.xml @@ -9,7 +9,7 @@ 101220 UKHO - + 1 ASSIGN CELL TO AVCS UNIT OF SALE AVCS UNIT @@ -30,8 +30,8 @@ N - - + + 2 CHANGE ENC CELL ENC CELL @@ -52,8 +52,8 @@ N - - + + 3 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -74,8 +74,8 @@ N - - + + 4 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -96,8 +96,8 @@ N - - + + 5 REMOVE ENC CELL FROM AVCS UNIT OF SALE AVCS UNIT @@ -118,7 +118,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MoveCell_AND_SuspendCell.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MoveCell_AND_SuspendCell.xml index 0566538e..d3a25863 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MoveCell_AND_SuspendCell.xml +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MoveCell_AND_SuspendCell.xml @@ -9,7 +9,7 @@ 015252 UKHO - + 1 ASSIGN CELL TO AVCS UNIT OF SALE AVCS UNIT @@ -30,8 +30,8 @@ N - - + + 2 CHANGE ENC CELL ENC CELL @@ -52,8 +52,8 @@ N - - + + 3 CHANGE ENC CELL ENC CELL @@ -74,8 +74,8 @@ N - - + + 4 CHANGE ENC CELL ENC CELL @@ -96,8 +96,8 @@ N - - + + 5 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -118,8 +118,8 @@ N - - + + 6 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -140,8 +140,8 @@ N - - + + 7 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -162,8 +162,8 @@ N - - + + 8 REMOVE ENC CELL FROM AVCS UNIT OF SALE AVCS UNIT @@ -184,7 +184,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MultipleCellsInSingleUnit.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MultipleCellsInSingleUnit.xml index 18e4eb8e..56331ab1 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MultipleCellsInSingleUnit.xml +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/MultipleCellsInSingleUnit.xml @@ -9,7 +9,7 @@ 015355 UKHO - + 1 ASSIGN CELL TO AVCS UNIT OF SALE AVCS UNIT @@ -30,8 +30,8 @@ N - - + + 2 ASSIGN CELL TO AVCS UNIT OF SALE AVCS UNIT @@ -52,8 +52,8 @@ N - - + + 3 ASSIGN CELL TO AVCS UNIT OF SALE AVCS UNIT @@ -74,8 +74,8 @@ N - - + + 4 CHANGE ENC CELL ENC CELL @@ -96,8 +96,8 @@ N - - + + 5 CHANGE ENC CELL ENC CELL @@ -118,8 +118,8 @@ N - - + + 6 CHANGE ENC CELL ENC CELL @@ -140,8 +140,8 @@ N - - + + 7 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -162,8 +162,8 @@ N - - + + 8 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -184,8 +184,8 @@ N - - + + 9 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -206,8 +206,8 @@ N - - + + 10 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -228,7 +228,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/NewCell.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/NewCell.xml index bb524fb6c804dc86aaa2b0ea941b13464a833707..c469a358e4af92469712124379989cfd963e8ed8 100644 GIT binary patch delta 75 zcmX?NeZ+c091COS=6IIRY>b(c=L;$W$#@pW%{#cCv7!jD2sxn&tP!^X3Bb|h=L;$W$#@pW%{#cCv7!jD2sxn&tP!^X3B3O6}a0X-ijkU(JIZ2)2ELn8nH delta 226 zcmZ3pgmKLh#tjK9jGmhlS@yCqdQLVJQU;QVERLI7xYwWxOcQ#*ilX9<#3odMFLF+( x0&`T*1YERiP*ptBM-%8U4MJAoyxGax4^`lYg9oa>3O6}a0X-ijkU(JIZ2qNZO3F}y8QjNMQ3Q?%I-v^Wh@%OJ$l9Q)*rpVR hDo~}71Q*!MsJ9r-0lR_A#1A4MJ6S-3Wpb6}E&#r9FCqW{ delta 164 zcmdl|vZZ8091El8WJW#5%?ns2u>qNZO3F}y8QjNMQ3Q?%I-v^Wh@%OJ$l9Q)*rpVR hDo~}71Q*!MsJ9r-0lR_A#1A4MJ6S-3Wpb6}E&u~jEaCtF diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/NewCell_AND_UoSMetadataChange.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/NewCell_AND_UoSMetadataChange.xml index a7647443b18e9bf11c995b49e041d7cb831144ea..210e7aa221a4520cb9dda998ecbe2acf8a311a46 100644 GIT binary patch delta 100 zcmZ4Dw#02i91COSWJhkt%?ns+*uYFhW*dgg&5qokSrJ^YidlkANJ5(##cPqcU=>ef RQXoRIlMMt}CTA(_0syDg8}0xA delta 100 zcmZ4Dw#02i91El8WJhkt%?ns+*uYFhW*Y|2&5qokSrJ^YidlkANJ5(##cPqcU=>ef RQXoRIlMMt}CTA(_0sv+;8m<5U diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/NewCell_AND_UpdateCell_AND_CellMetadataChange.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/NewCell_AND_UpdateCell_AND_CellMetadataChange.xml index a3f0435b1aade8e57e0230270a20635abb1c854e..075c64cb8df10a30059573c14d1f6b59f6bdbe37 100644 GIT binary patch delta 152 zcmZ2ewx(=D91COSWJhkt%?ns+*nrH7y2^~1n;p47v%)xF*;#^4aDmN?;3Gcsxb delta 152 zcmZ2ewx(=D91El8WJhkt%?ns+*nrH7y2^~6n;p47v%)xF*;#^4aDmN?;053558 UKHO - + 1 CREATE ENC CELL ENC CELL @@ -30,8 +30,8 @@ N ThisWillBeRetrievedFromKeyVaultBeforeAssertion ThisWillBeRetrievedFromKeyVaultBeforeAssertion - - + + 2 CREATE AVCS UNIT OF SALE AVCS UNIT @@ -52,8 +52,8 @@ N - - + + 3 ASSIGN CELL TO AVCS UNIT OF SALE AVCS UNIT @@ -74,8 +74,8 @@ N - - + + 4 ASSIGN CELL TO AVCS UNIT OF SALE AVCS UNIT @@ -96,7 +96,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/SuspendCell.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/SuspendCell.xml index e8db52c0..c36516c1 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/SuspendCell.xml +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/SuspendCell.xml @@ -9,7 +9,7 @@ 020436 UKHO - + 1 CHANGE ENC CELL ENC CELL @@ -30,8 +30,8 @@ N - - + + 2 CHANGE ENC CELL ENC CELL @@ -52,8 +52,8 @@ N - - + + 3 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -74,7 +74,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/SuspendCell_AND_WithdrawCell.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/SuspendCell_AND_WithdrawCell.xml index 90484aaf..fd07c499 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/SuspendCell_AND_WithdrawCell.xml +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/SuspendCell_AND_WithdrawCell.xml @@ -9,7 +9,7 @@ 020613 UKHO - + 1 CHANGE ENC CELL ENC CELL @@ -30,8 +30,8 @@ N - - + + 2 CHANGE ENC CELL ENC CELL @@ -52,8 +52,8 @@ N - - + + 3 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -74,8 +74,8 @@ N - - + + 4 REMOVE ENC CELL FROM AVCS UNIT OF SALE AVCS UNIT @@ -96,8 +96,8 @@ N - - + + 5 REMOVE ENC CELL FROM AVCS UNIT OF SALE AVCS UNIT @@ -118,8 +118,8 @@ N - - + + 6 CANCEL AVCS UNIT OF SALE AVCS UNIT @@ -140,7 +140,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/UoSMetadataChange.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/UoSMetadataChange.xml index d4032ca6..6de99f79 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/UoSMetadataChange.xml +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/UoSMetadataChange.xml @@ -9,7 +9,7 @@ 101350 UKHO - + 1 CHANGE AVCS UNIT OF SALE AVCS UNIT @@ -30,7 +30,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/UpdateCell.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/UpdateCell.xml index f1103eec0324b25a49dfdb8ba254df84a2481efa..3283bd9aec9ba60a7f819a6b000027617a4d7a3f 100644 GIT binary patch delta 54 vcmcbmcS~$#@pW%_&?-r~*0yL2N*|da>I81-ud! delta 54 vcmcbmcS~$#@pW%_&?-r~*0yL2N*|da>I8@r@Bx diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/UpdateCellWithNewEdition.xml b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadeExpectedXmlFiles/UpdateCellWithNewEdition.xml index 04b2840117441414d2b9026708648d2cb04787ee..9af838d45602f738762e08d35cacbbb62b43b0bc 100644 GIT binary patch delta 70 zcmcbmcS~101534 UKHO - + 1 REMOVE ENC CELL FROM AVCS UNIT OF SALE AVCS UNIT @@ -30,8 +30,8 @@ N - - + + 2 REMOVE ENC CELL FROM AVCS UNIT OF SALE AVCS UNIT @@ -52,8 +52,8 @@ N - - + + 3 CANCEL AVCS UNIT OF SALE AVCS UNIT @@ -74,7 +74,7 @@ N - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/SAPXmlHelper.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/SAPXmlHelper.cs index 3443d8b3..1430ecdb 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/SAPXmlHelper.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/SAPXmlHelper.cs @@ -64,8 +64,8 @@ public static bool VerifyGeneratedXml(string generatedXmlFilePath, string xmlFil expectedXml = XElement.Load(reader); } - var generatedAttributes = generatedXml.Descendants("Item").ToList(); - var expectedAttributes = expectedXml.Descendants("Item").ToList(); + var generatedAttributes = generatedXml.Descendants("item").ToList(); + var expectedAttributes = expectedXml.Descendants("item").ToList(); string activeKey = permitState == "PermitWithSameKey" ? permitWithSameKeyActiveKey : permitWithDifferentKeyActiveKey; From 2bad453c45b6c778c1ab2a7cec9ee5d38ca197b2 Mon Sep 17 00:00:00 2001 From: rushdynajath Date: Fri, 11 Oct 2024 16:54:37 +0100 Subject: [PATCH 3/8] Merge main into develop 11_10 (#210) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump System.Runtime.Caching in /src/UKHO.ERPFacade.Common (#199) Bumps [System.Runtime.Caching](https://github.com/dotnet/runtime) from 8.0.0 to 8.0.1. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) --- updated-dependencies: - dependency-name: System.Runtime.Caching dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump the all-packages group with 4 updates (#196) * Bump the all-packages group with 4 updates Bumps the all-packages group with 4 updates: [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore), [SoapCore](https://github.com/DigDes/SoapCore), [RestSharp](https://github.com/restsharp/RestSharp) and [WireMock.Net](https://github.com/WireMock-Net/WireMock.Net). Updates `Swashbuckle.AspNetCore` from 6.8.0 to 6.8.1 - [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases) - [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.8.0...v6.8.1) Updates `SoapCore` from 1.1.0.49 to 1.1.0.51 - [Release notes](https://github.com/DigDes/SoapCore/releases) - [Commits](https://github.com/DigDes/SoapCore/compare/v1.1.0.49...v1.1.0.51) Updates `RestSharp` from 112.0.0 to 112.1.0 - [Release notes](https://github.com/restsharp/RestSharp/releases) - [Commits](https://github.com/restsharp/RestSharp/compare/112.0.0...112.1.0) Updates `WireMock.Net` from 1.6.5 to 1.6.6 - [Release notes](https://github.com/WireMock-Net/WireMock.Net/releases) - [Changelog](https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md) - [Commits](https://github.com/WireMock-Net/WireMock.Net/compare/1.6.5...1.6.6) --- updated-dependencies: - dependency-name: Swashbuckle.AspNetCore dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: SoapCore dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: RestSharp dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-packages - dependency-name: WireMock.Net dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages ... Signed-off-by: dependabot[bot] * Add suppression for CVE-2024-43483 in System.Runtime.Caching * Add suppression for CVE-2022-34716 in System.Security.Cryptography.Xml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: HugoBurgess <128484816+HugoBurgess@users.noreply.github.com> Co-authored-by: rushdynajath * Bump System.Text.Json from 8.0.4 to 8.0.5 in /src/UKHO.ERPFacade.API (#200) Bumps [System.Text.Json](https://github.com/dotnet/runtime) from 8.0.4 to 8.0.5. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) --- updated-dependencies: - dependency-name: System.Text.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump System.Text.Json in /src/UKHO.ERPFacade.CleanUp.WebJob (#207) Bumps [System.Text.Json](https://github.com/dotnet/runtime) from 8.0.4 to 8.0.5. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) --- updated-dependencies: - dependency-name: System.Text.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Refactor Azure Pipelines YAML to streamline permit configuration vari… (#211) * Refactor Azure Pipelines YAML to streamline permit configuration variables * Add PermitDecryptionHardwareId to Azure Pipelines configuration --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: HugoBurgess <128484816+HugoBurgess@users.noreply.github.com> --- NVDSuppressions.xml | 14 +++++++++++ azure-pipelines.yml | 24 +++++++------------ .../UKHO.ERPFacade.API.csproj | 2 +- .../UKHO.ERPFacade.CleanUp.WebJob.csproj | 2 +- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/NVDSuppressions.xml b/NVDSuppressions.xml index 3b988eb9..a3ee45bd 100644 --- a/NVDSuppressions.xml +++ b/NVDSuppressions.xml @@ -775,6 +775,20 @@ ^pkg:nuget/System\.Runtime\.Caching@.*$ CVE-2024-43483 + + + ^pkg:nuget/System\.Security\.Cryptography\.Xml@.*$ + CVE-2022-34716 + + + + ^pkg:nuget/System\.Runtime\.Caching@.*$ + CVE-2024-43483 + - + diff --git a/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj b/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj index a5e59d54..2fa6bf49 100644 --- a/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj +++ b/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj @@ -42,7 +42,7 @@ - + From d872bda2d7ba07ae69c74ec4ddcfb2ff93a9827d Mon Sep 17 00:00:00 2001 From: pravinvarade10801 <124246537+pravinvarade10801@users.noreply.github.com> Date: Mon, 14 Oct 2024 16:14:48 +0530 Subject: [PATCH 4/8] 181621 adds live defect fix permit decryption failure (#208) * 181621-permit decryption failure issue fixed AB#181621 * 181621-Added FT for permit decryption failure AB#181621 * 181621-code refactored AB#181621 --------- Co-authored-by: rushikeshkhopatkar Co-authored-by: rushdynajath Co-authored-by: Vishal14583 <61726015+Vishal14583@users.noreply.github.com> --- .../Helpers/EncContentSapMessageBuilder.cs | 8 +++----- src/UKHO.ERPFacade.Common/Logging/EventIds.cs | 12 ++++++++++- .../PermitDecryption/PermitDecryption.cs | 15 +++++++++++--- .../FunctionalTests/WebhookScenarios.cs | 9 +++++++++ .../Helpers/SAPXmlHelper.cs | 2 +- .../EncContentSapMessageBuilderTests.cs | 20 +------------------ 6 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs b/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs index 892e37ad..0d561b31 100644 --- a/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs +++ b/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs @@ -299,7 +299,7 @@ private XmlElement BuildAction(XmlDocument soapXml, Product product, UnitOfSale List<(int sortingOrder, XmlElement node)> actionAttributes = new(); // Get permit keys for New cell and Updated cell - if (product != null! && !IsPropertyNullOrEmpty(Permit, product.Permit) && (action.Action == CreateEncCell || action.Action == UpdateCell)) + if (action.Action == CreateEncCell || action.Action == UpdateCell) { decryptedPermit = _permitDecryption.Decrypt(product.Permit); } @@ -345,12 +345,10 @@ private void ProcessAttributes(string action, IEnumerable a if (!IsPropertyNullOrEmpty(attribute.JsonPropertyName, replacedBy)) attributeNode.InnerText = GetXmlNodeValue(replacedBy.ToString(), attribute.XmlNodeName); break; case ActiveKey: - attributeNode.InnerText = string.Empty; - if (decryptedPermit != null && !string.IsNullOrEmpty(decryptedPermit.ActiveKey)) attributeNode.InnerText = GetXmlNodeValue(decryptedPermit.ActiveKey, attribute.XmlNodeName); + if (!IsPropertyNullOrEmpty(attribute.JsonPropertyName, decryptedPermit.ActiveKey)) attributeNode.InnerText = GetXmlNodeValue(decryptedPermit.ActiveKey, attribute.XmlNodeName); break; case NextKey: - attributeNode.InnerText = string.Empty; - if (decryptedPermit != null && !string.IsNullOrEmpty(decryptedPermit.NextKey)) attributeNode.InnerText = GetXmlNodeValue(decryptedPermit.NextKey, attribute.XmlNodeName); + if (!IsPropertyNullOrEmpty(attribute.JsonPropertyName, decryptedPermit.NextKey)) attributeNode.InnerText = GetXmlNodeValue(decryptedPermit.NextKey, attribute.XmlNodeName); break; default: var jsonFieldValue = CommonHelper.ParseXmlNode(attribute.JsonPropertyName, source, source.GetType()).ToString(); diff --git a/src/UKHO.ERPFacade.Common/Logging/EventIds.cs b/src/UKHO.ERPFacade.Common/Logging/EventIds.cs index 3a8799e2..f8d82346 100644 --- a/src/UKHO.ERPFacade.Common/Logging/EventIds.cs +++ b/src/UKHO.ERPFacade.Common/Logging/EventIds.cs @@ -436,7 +436,17 @@ public enum EventIds /// /// 940086 - Required section not found in JSON payload. /// - RequiredSectionNotFoundException = 940086 + RequiredSectionNotFoundException = 940086, + + /// + /// 940087 - Hardware Id not found in configuration. + /// + HardwareIdNotFoundException = 940087, + + /// + /// 940088 - Permit string provided empty in json payload. + /// + EmptyPermitStringException = 940088 } /// diff --git a/src/UKHO.ERPFacade.Common/PermitDecryption/PermitDecryption.cs b/src/UKHO.ERPFacade.Common/PermitDecryption/PermitDecryption.cs index b3cbeb24..538de181 100644 --- a/src/UKHO.ERPFacade.Common/PermitDecryption/PermitDecryption.cs +++ b/src/UKHO.ERPFacade.Common/PermitDecryption/PermitDecryption.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using UKHO.ERPFacade.Common.Configuration; +using UKHO.ERPFacade.Common.Exceptions; using UKHO.ERPFacade.Common.Logging; using UKHO.ERPFacade.Common.Models; @@ -18,11 +19,20 @@ public PermitDecryption(ILogger logger, IOptions(() => _fakeEncContentSapMessageBuilder.BuildSapMessageXml(eventData!)) .Message.Should().Be("Error while generating SAP action information. | Action : CREATE ENC CELL | XML Attribute : VALIDFROM | ErrorMessage : Exception of type 'System.Exception' was thrown."); - } - - [Test] - public void WhenBuildSapMessageXmlWithEmptyPermit_ThenThrowERPFacadeException() - { - var newCellEventPayloadJson = TestHelper.ReadFileData("ERPTestData\\NewCellWithEmptyPermit.JSON"); - var eventData = JsonConvert.DeserializeObject(newCellEventPayloadJson); - - XmlDocument soapXml = new(); - soapXml.LoadXml(_sapXmlTemplate); - - A.CallTo(() => _fakeFileSystemHelper.IsFileExists(A.Ignored)).Returns(true); - A.CallTo(() => _fakeXmlHelper.CreateXmlDocument(A.Ignored)).Returns(soapXml); - - A.CallTo(() => _fakeWeekDetailsProvider.GetDateOfWeek(A.Ignored, A.Ignored, A.Ignored)).Throws(); - - Assert.Throws(() => _fakeEncContentSapMessageBuilder.BuildSapMessageXml(eventData!)) - .Message.Should().Be("Required details are missing in enccontentpublished event payload. | Property Name : permit"); - } + } [Test] public void WhenUnitOfSaleIsNullWhileReplacingEncCell_ThenReturnsNull() From 408df940d5a7e9067852470bc5ef3a66e7470797 Mon Sep 17 00:00:00 2001 From: rushdynajath Date: Mon, 14 Oct 2024 14:31:23 +0100 Subject: [PATCH 5/8] Dependabot main into developement14 10 (#214) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump System.Runtime.Caching in /src/UKHO.ERPFacade.Common (#199) Bumps [System.Runtime.Caching](https://github.com/dotnet/runtime) from 8.0.0 to 8.0.1. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) --- updated-dependencies: - dependency-name: System.Runtime.Caching dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump the all-packages group with 4 updates (#196) * Bump the all-packages group with 4 updates Bumps the all-packages group with 4 updates: [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore), [SoapCore](https://github.com/DigDes/SoapCore), [RestSharp](https://github.com/restsharp/RestSharp) and [WireMock.Net](https://github.com/WireMock-Net/WireMock.Net). Updates `Swashbuckle.AspNetCore` from 6.8.0 to 6.8.1 - [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases) - [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.8.0...v6.8.1) Updates `SoapCore` from 1.1.0.49 to 1.1.0.51 - [Release notes](https://github.com/DigDes/SoapCore/releases) - [Commits](https://github.com/DigDes/SoapCore/compare/v1.1.0.49...v1.1.0.51) Updates `RestSharp` from 112.0.0 to 112.1.0 - [Release notes](https://github.com/restsharp/RestSharp/releases) - [Commits](https://github.com/restsharp/RestSharp/compare/112.0.0...112.1.0) Updates `WireMock.Net` from 1.6.5 to 1.6.6 - [Release notes](https://github.com/WireMock-Net/WireMock.Net/releases) - [Changelog](https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md) - [Commits](https://github.com/WireMock-Net/WireMock.Net/compare/1.6.5...1.6.6) --- updated-dependencies: - dependency-name: Swashbuckle.AspNetCore dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: SoapCore dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: RestSharp dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-packages - dependency-name: WireMock.Net dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages ... Signed-off-by: dependabot[bot] * Add suppression for CVE-2024-43483 in System.Runtime.Caching * Add suppression for CVE-2022-34716 in System.Security.Cryptography.Xml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: HugoBurgess <128484816+HugoBurgess@users.noreply.github.com> Co-authored-by: rushdynajath * Bump System.Text.Json from 8.0.4 to 8.0.5 in /src/UKHO.ERPFacade.API (#200) Bumps [System.Text.Json](https://github.com/dotnet/runtime) from 8.0.4 to 8.0.5. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) --- updated-dependencies: - dependency-name: System.Text.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump System.Text.Json in /src/UKHO.ERPFacade.CleanUp.WebJob (#207) Bumps [System.Text.Json](https://github.com/dotnet/runtime) from 8.0.4 to 8.0.5. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) --- updated-dependencies: - dependency-name: System.Text.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Refactor Azure Pipelines YAML to streamline permit configuration vari… (#211) * Refactor Azure Pipelines YAML to streamline permit configuration variables * Add PermitDecryptionHardwareId to Azure Pipelines configuration * Bump the all-packages group with 20 updates (#212) Bumps the all-packages group with 20 updates: | Package | From | To | | --- | --- | --- | | [Elastic.Apm.NetCoreAll](https://github.com/elastic/apm-agent-dotnet) | `1.29.0` | `1.30.0` | | [Microsoft.AspNetCore.Authentication.JwtBearer](https://github.com/dotnet/aspnetcore) | `6.0.33` | `6.0.35` | | [Microsoft.AspNetCore.HeaderPropagation](https://github.com/dotnet/aspnetcore) | `6.0.33` | `6.0.35` | | [Microsoft.AspNetCore.Mvc.NewtonsoftJson](https://github.com/dotnet/aspnetcore) | `6.0.33` | `6.0.35` | | [Microsoft.Extensions.Diagnostics.HealthChecks](https://github.com/dotnet/aspnetcore) | `8.0.8` | `8.0.10` | | [Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions](https://github.com/dotnet/aspnetcore) | `8.0.8` | `8.0.10` | | [Microsoft.Extensions.Logging.Abstractions](https://github.com/dotnet/runtime) | `8.0.1` | `8.0.2` | | [Microsoft.Extensions.Logging.AzureAppServices](https://github.com/dotnet/aspnetcore) | `8.0.8` | `8.0.10` | | [Microsoft.Extensions.Configuration.Json](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [System.Text.Json](https://github.com/dotnet/runtime) | `8.0.4` | `8.0.5` | | [Microsoft.Extensions.Logging](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [Microsoft.Extensions.DependencyInjection](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [Microsoft.Extensions.Logging.Console](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [Microsoft.Extensions.Logging.Debug](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [Azure.Storage.Blobs](https://github.com/Azure/azure-sdk-for-net) | `12.22.1` | `12.22.2` | | [Azure.Storage.Queues](https://github.com/Azure/azure-sdk-for-net) | `12.20.0` | `12.20.1` | | [Microsoft.Extensions.Http](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [Microsoft.Extensions.Http.Polly](https://github.com/dotnet/aspnetcore) | `8.0.8` | `8.0.10` | | [Microsoft.Azure.WebJobs.Extensions.Storage](https://github.com/Azure/azure-sdk-for-net) | `5.3.2` | `5.3.3` | | [Microsoft.Extensions.Hosting](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | Updates `Elastic.Apm.NetCoreAll` from 1.29.0 to 1.30.0 - [Release notes](https://github.com/elastic/apm-agent-dotnet/releases) - [Changelog](https://github.com/elastic/apm-agent-dotnet/blob/main/CHANGELOG.asciidoc) - [Commits](https://github.com/elastic/apm-agent-dotnet/compare/v1.29.0...v1.30.0) Updates `Microsoft.AspNetCore.Authentication.JwtBearer` from 6.0.33 to 6.0.35 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v6.0.33...v6.0.35) Updates `Microsoft.AspNetCore.HeaderPropagation` from 6.0.33 to 6.0.35 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v6.0.33...v6.0.35) Updates `Microsoft.AspNetCore.Mvc.NewtonsoftJson` from 6.0.33 to 6.0.35 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v6.0.33...v6.0.35) Updates `Microsoft.Extensions.Diagnostics.HealthChecks` from 8.0.8 to 8.0.10 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v8.0.8...v8.0.10) Updates `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions` from 8.0.8 to 8.0.10 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v8.0.8...v8.0.10) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions` from 8.0.8 to 8.0.10 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v8.0.8...v8.0.10) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging.AzureAppServices` from 8.0.8 to 8.0.10 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v8.0.8...v8.0.10) Updates `Microsoft.Extensions.Configuration.Json` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `System.Text.Json` from 8.0.4 to 8.0.5 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging.Console` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `System.Text.Json` from 8.0.4 to 8.0.5 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) Updates `System.Text.Json` from 8.0.4 to 8.0.5 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) Updates `Microsoft.Extensions.Configuration.Json` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `System.Text.Json` from 8.0.4 to 8.0.5 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Debug` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Azure.Storage.Blobs` from 12.22.1 to 12.22.2 - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Storage.Blobs_12.22.1...Azure.Storage.Blobs_12.22.2) Updates `Azure.Storage.Queues` from 12.20.0 to 12.20.1 - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Storage.Queues_12.20.0...Azure.Storage.Queues_12.20.1) Updates `Microsoft.Extensions.Http` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Http.Polly` from 8.0.8 to 8.0.10 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v8.0.8...v8.0.10) Updates `Microsoft.Extensions.Http` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Azure.WebJobs.Extensions.Storage` from 5.3.2 to 5.3.3 - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Microsoft.Azure.WebJobs.Extensions.Storage_5.3.2...Microsoft.Azure.WebJobs.Extensions.Storage_5.3.3) Updates `Microsoft.Extensions.Hosting` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Configuration.Json` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `System.Text.Json` from 8.0.4 to 8.0.5 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Console` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Debug` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) --- updated-dependencies: - dependency-name: Elastic.Apm.NetCoreAll dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-packages - dependency-name: Microsoft.AspNetCore.Authentication.JwtBearer dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.AspNetCore.HeaderPropagation dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.AspNetCore.Mvc.NewtonsoftJson dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Diagnostics.HealthChecks dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.AzureAppServices dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Configuration.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Console dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Configuration.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Debug dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Azure.Storage.Blobs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Azure.Storage.Queues dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Http dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Http.Polly dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Http dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Azure.WebJobs.Extensions.Storage dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Hosting dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Configuration.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Console dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Debug dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: HugoBurgess <128484816+HugoBurgess@users.noreply.github.com> --- src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj | 14 +++++++------- .../UKHO.ERPFacade.CleanUp.WebJob.csproj | 10 +++++----- .../UKHO.ERPFacade.Common.csproj | 12 ++++++------ .../UKHO.ERPFacade.EventAggregation.WebJob.csproj | 12 ++++++------ .../UKHO.SAP.MockAPIService.csproj | 2 +- .../UKHO.ERPFacade.API.FunctionalTests.csproj | 4 ++-- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj b/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj index 2fc52427..d5e95c91 100644 --- a/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj +++ b/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj @@ -36,16 +36,16 @@ - + - - - - + + + + - - + + diff --git a/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj b/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj index 2fa6bf49..a15b921e 100644 --- a/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj +++ b/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj @@ -34,11 +34,11 @@ - - - - - + + + + + diff --git a/src/UKHO.ERPFacade.Common/UKHO.ERPFacade.Common.csproj b/src/UKHO.ERPFacade.Common/UKHO.ERPFacade.Common.csproj index 2c660fc1..6ee92ff5 100644 --- a/src/UKHO.ERPFacade.Common/UKHO.ERPFacade.Common.csproj +++ b/src/UKHO.ERPFacade.Common/UKHO.ERPFacade.Common.csproj @@ -17,16 +17,16 @@ - - + + - + - - - + + + diff --git a/src/UKHO.ERPFacade.EventAggregation.WebJob/UKHO.ERPFacade.EventAggregation.WebJob.csproj b/src/UKHO.ERPFacade.EventAggregation.WebJob/UKHO.ERPFacade.EventAggregation.WebJob.csproj index f14f019a..93225822 100644 --- a/src/UKHO.ERPFacade.EventAggregation.WebJob/UKHO.ERPFacade.EventAggregation.WebJob.csproj +++ b/src/UKHO.ERPFacade.EventAggregation.WebJob/UKHO.ERPFacade.EventAggregation.WebJob.csproj @@ -28,15 +28,15 @@ - + - - - - + + + + - + diff --git a/src/UKHO.SAP.MockAPIService/UKHO.SAP.MockAPIService.csproj b/src/UKHO.SAP.MockAPIService/UKHO.SAP.MockAPIService.csproj index 06ac77ac..149b48cb 100644 --- a/src/UKHO.SAP.MockAPIService/UKHO.SAP.MockAPIService.csproj +++ b/src/UKHO.SAP.MockAPIService/UKHO.SAP.MockAPIService.csproj @@ -21,7 +21,7 @@ - + diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj b/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj index 939dcc9e..791e5621 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj @@ -26,8 +26,8 @@ - - + + From 32484b164efa93e14ee35b726e2b86c489d9729b Mon Sep 17 00:00:00 2001 From: pravinvarade10801 <124246537+pravinvarade10801@users.noreply.github.com> Date: Mon, 14 Oct 2024 20:33:31 +0530 Subject: [PATCH 6/8] 181933 storage container structure changes (#213) * 181933-storage structure modified and code uplifted AB#181933 * 181933- Resolved unit test AB#181933 * 181933-unit tests fixed AB#181933 * 181933-download xml method changes for FTs AB#181933 * 181933-Removed unused method AB#181933 * 181933-constant file added AB#181933 * 181933-nuget pacakges upgraded AB#181933 * 181933-missing template file added AB#181933 * 181933-storage ros table name constant updated AB#181933 * 181933-variable name updated AB#181933 * 181933-code review comments fixed AB#181933 * 181933-build error fixed AB#181933 * 181933-Moved all constants to common file AB#181933 * 181933-Updated Constant AB#181933 --------- Co-authored-by: Vishal Dukare Co-authored-by: Gaurav Mejari Co-authored-by: rushikeshkhopatkar --- .../Controllers/WebhookController.cs | 67 +++--- .../Health/HealthResponseWriter.cs | 6 +- .../Helpers/EncContentSapMessageBuilder.cs | 108 ++++------ .../LicenceUpdatedSapMessageBuilder.cs | 11 +- .../{RosSapRequest.xml => SAPRoSRequest.xml} | 0 .../{SAPRequest.xml => SAPS57Request.xml} | 0 .../UKHO.ERPFacade.API.csproj | 4 +- .../Services/CleanUpService.cs | 30 +-- .../UKHO.ERPFacade.CleanUp.WebJob.csproj | 3 - .../Constants/Constants.cs | 145 +++++++++++++ src/UKHO.ERPFacade.Common/Enums/Status.cs | 8 + .../IO/Azure/AzureBlobEventWriter.cs | 15 ++ .../IO/Azure/AzureQueueHelper.cs | 3 +- .../IO/Azure/AzureTableReaderWriter.cs | 192 +++--------------- .../IO/Azure/IAzureBlobEventWriter.cs | 8 +- .../IO/Azure/IAzureTableReaderWriter.cs | 18 +- .../{EESEventEntity.cs => EncEventEntity.cs} | 2 +- .../LicenseUpdatedEventEntity.cs | 22 ++ .../EventAggregationWebjob.cs | 4 +- .../Helpers/RecordOfSaleSapMessageBuilder.cs | 30 +-- .../{RosSapRequest.xml => SAPRoSRequest.xml} | 0 .../Services/AggregationService.cs | 20 +- ...O.ERPFacade.EventAggregation.WebJob.csproj | 2 +- .../Configuration/TestConfig.cs | 1 - .../FunctionalTests/RoSWebhookScenarios.cs | 25 +-- .../FunctionalTests/WebhookScenarios.cs | 20 +- .../Helpers/AzureBlobStorageHelper.cs | 24 +-- .../Helpers/AzureTableHelper.cs | 8 +- .../Helpers/JSONHelper.cs | 15 +- .../Helpers/LicenceUpdateXMLHelper.cs | 9 +- .../Helpers/RoSXMLHelper.cs | 27 +-- .../Helpers/SAPXmlHelper.cs | 22 +- .../Service/LicenceUpdatedEndpoint.cs | 15 +- .../Service/RoSWebhookEndpoint.cs | 29 ++- ...bhookEndpoint.cs => S57WebhookEndpoint.cs} | 19 +- .../Controllers/WebhookControllerTests.cs | 28 ++- .../EncContentSapMessageBuilderTests.cs | 28 +-- .../Services/CleanUpServiceTests.cs | 148 +++++++------- .../Services/AggregationServiceTests.cs | 62 ++++-- 39 files changed, 586 insertions(+), 592 deletions(-) rename src/UKHO.ERPFacade.API/SapXmlTemplates/{RosSapRequest.xml => SAPRoSRequest.xml} (100%) rename src/UKHO.ERPFacade.API/SapXmlTemplates/{SAPRequest.xml => SAPS57Request.xml} (100%) create mode 100644 src/UKHO.ERPFacade.Common/Constants/Constants.cs create mode 100644 src/UKHO.ERPFacade.Common/Enums/Status.cs rename src/UKHO.ERPFacade.Common/Models/TableEntities/{EESEventEntity.cs => EncEventEntity.cs} (92%) create mode 100644 src/UKHO.ERPFacade.Common/Models/TableEntities/LicenseUpdatedEventEntity.cs rename src/UKHO.ERPFacade.EventAggregation.WebJob/SapXmlTemplates/{RosSapRequest.xml => SAPRoSRequest.xml} (100%) rename tests/UKHO.ERPFacade.API.FunctionalTests/Service/{WebhookEndpoint.cs => S57WebhookEndpoint.cs} (86%) diff --git a/src/UKHO.ERPFacade.API/Controllers/WebhookController.cs b/src/UKHO.ERPFacade.API/Controllers/WebhookController.cs index 91a2217b..1dd21e67 100644 --- a/src/UKHO.ERPFacade.API/Controllers/WebhookController.cs +++ b/src/UKHO.ERPFacade.API/Controllers/WebhookController.cs @@ -5,12 +5,15 @@ using Newtonsoft.Json.Linq; using UKHO.ERPFacade.API.Helpers; using UKHO.ERPFacade.Common.Configuration; +using UKHO.ERPFacade.Common.Constants; using UKHO.ERPFacade.Common.Exceptions; using UKHO.ERPFacade.Common.HttpClients; using UKHO.ERPFacade.Common.IO; using UKHO.ERPFacade.Common.IO.Azure; using UKHO.ERPFacade.Common.Logging; using UKHO.ERPFacade.Common.Models; +using UKHO.ERPFacade.Common.Models.TableEntities; +using Status = UKHO.ERPFacade.Common.Enums.Status; namespace UKHO.ERPFacade.API.Controllers { @@ -28,15 +31,6 @@ public class WebhookController : BaseController private readonly IOptions _sapConfig; private readonly ILicenceUpdatedSapMessageBuilder _licenceUpdatedSapMessageBuilder; - private const string EventIdKey = "id"; - private const string CorrelationIdKey = "data.correlationId"; - private const string EncEventFileName = "EncPublishingEvent.json"; - private const string SapXmlPayloadFileName = "SapXmlPayload.xml"; - private const string LicenceUpdatedContainerName = "licenceupdatedblobs"; - private const string LicenceUpdatedEventFileName = "LicenceUpdatedEvent.json"; - private const string RecordOfSaleContainerName = "recordofsaleblobs"; - private const string JsonFileType = ".json"; - public WebhookController(IHttpContextAccessor contextAccessor, ILogger logger, IAzureTableReaderWriter azureTableReaderWriter, @@ -82,7 +76,7 @@ public virtual async Task NewEncContentPublishedEventReceived([Fr { _logger.LogInformation(EventIds.NewEncContentPublishedEventReceived.ToEventId(), "ERP Facade webhook has received new enccontentpublished event from EES."); - var correlationId = encEventJson.SelectToken(CorrelationIdKey)?.Value(); + var correlationId = encEventJson.SelectToken(Constants.CorrelationIdKey)?.Value(); if (string.IsNullOrEmpty(correlationId)) { @@ -90,17 +84,26 @@ public virtual async Task NewEncContentPublishedEventReceived([Fr return new BadRequestObjectResult(StatusCodes.Status400BadRequest); } + EncEventEntity encEventEntity = new() + { + RowKey = Guid.NewGuid().ToString(), + PartitionKey = Guid.NewGuid().ToString(), + Timestamp = DateTime.UtcNow, + CorrelationId = correlationId, + RequestDateTime = null + }; + _logger.LogInformation(EventIds.AddingEntryForEncContentPublishedEventInAzureTable.ToEventId(), "Adding/Updating entry for enccontentpublished event in azure table."); - await _azureTableReaderWriter.UpsertEntity(correlationId); + await _azureTableReaderWriter.UpsertEntity(correlationId, Constants.S57EventTableName, encEventEntity); _logger.LogInformation(EventIds.UploadEncContentPublishedEventInAzureBlobStarted.ToEventId(), "Uploading enccontentpublished event payload in blob storage."); - await _azureBlobEventWriter.UploadEvent(encEventJson.ToString(), correlationId, EncEventFileName); + await _azureBlobEventWriter.UploadEvent(encEventJson.ToString(), Constants.S57EventContainerName, correlationId + '/' + Constants.S57EncEventFileName); _logger.LogInformation(EventIds.UploadEncContentPublishedEventInAzureBlobCompleted.ToEventId(), "The enccontentpublished event payload is uploaded in blob storage successfully."); var sapPayload = _encContentSapMessageBuilder.BuildSapMessageXml(JsonConvert.DeserializeObject(encEventJson.ToString())); _logger.LogInformation(EventIds.UploadSapXmlPayloadInAzureBlobStarted.ToEventId(), "Uploading the SAP XML payload in blob storage."); - await _azureBlobEventWriter.UploadEvent(sapPayload.ToIndentedString(), correlationId, SapXmlPayloadFileName); + await _azureBlobEventWriter.UploadEvent(sapPayload.ToIndentedString(), Constants.S57EventContainerName, correlationId + '/' + Constants.SapXmlPayloadFileName); _logger.LogInformation(EventIds.UploadSapXmlPayloadInAzureBlobCompleted.ToEventId(), "SAP XML payload is uploaded in blob storage successfully."); var response = await _sapClient.PostEventData(sapPayload, _sapConfig.Value.SapEndpointForEncEvent, _sapConfig.Value.SapServiceOperationForEncEvent, _sapConfig.Value.SapUsernameForEncEvent, _sapConfig.Value.SapPasswordForEncEvent); @@ -111,7 +114,7 @@ public virtual async Task NewEncContentPublishedEventReceived([Fr } _logger.LogInformation(EventIds.EncUpdateSentToSap.ToEventId(), "ENC update has been sent to SAP successfully. | {StatusCode}", response.StatusCode); - await _azureTableReaderWriter.UpdateRequestTimeEntity(correlationId); + await _azureTableReaderWriter.UpdateEntity(correlationId, Constants.S57EventTableName, new[] { new KeyValuePair("RequestDateTime", DateTime.UtcNow) }); return new OkObjectResult(StatusCodes.Status200OK); } @@ -142,8 +145,8 @@ public virtual async Task RecordOfSalePublishedEventReceived([Fro { _logger.LogInformation(EventIds.RecordOfSalePublishedEventReceived.ToEventId(), "ERP Facade webhook has received record of sale event from EES."); - var correlationId = recordOfSaleEventJson.SelectToken(CorrelationIdKey)?.Value(); - var eventId = recordOfSaleEventJson.SelectToken(EventIdKey)?.Value(); + var correlationId = recordOfSaleEventJson.SelectToken(Constants.CorrelationIdKey)?.Value(); + var eventId = recordOfSaleEventJson.SelectToken(Constants.EventIdKey)?.Value(); if (string.IsNullOrEmpty(correlationId)) { @@ -151,11 +154,20 @@ public virtual async Task RecordOfSalePublishedEventReceived([Fro return new BadRequestObjectResult(StatusCodes.Status400BadRequest); } + RecordOfSaleEventEntity recordOfSaleEvent = new() + { + RowKey = Guid.NewGuid().ToString(), + PartitionKey = Guid.NewGuid().ToString(), + Timestamp = DateTime.UtcNow, + CorrelationId = correlationId, + Status = Status.Incomplete.ToString() + }; + _logger.LogInformation(EventIds.StoreRecordOfSalePublishedEventInAzureTable.ToEventId(), "Storing the received Record of sale published event in azure table."); - await _azureTableReaderWriter.UpsertRecordOfSaleEntity(correlationId); + await _azureTableReaderWriter.UpsertEntity(correlationId, Constants.RecordOfSaleEventTableName, recordOfSaleEvent); _logger.LogInformation(EventIds.UploadRecordOfSalePublishedEventInAzureBlob.ToEventId(), "Uploading the received Record of sale published event in blob storage."); - await _azureBlobEventWriter.UploadEvent(recordOfSaleEventJson.ToString(), RecordOfSaleContainerName, correlationId + '/' + eventId + JsonFileType); + await _azureBlobEventWriter.UploadEvent(recordOfSaleEventJson.ToString(), Constants.RecordOfSaleEventContainerName, correlationId + '/' + eventId + Constants.RecordOfSaleEventFileExtension); _logger.LogInformation(EventIds.UploadedRecordOfSalePublishedEventInAzureBlob.ToEventId(), "Record of sale published event is uploaded in blob storage successfully."); _logger.LogInformation(EventIds.AddMessageToAzureQueue.ToEventId(), "Adding the received Record of sale published event in queue storage."); @@ -191,7 +203,7 @@ public virtual async Task LicenceUpdatedPublishedEventReceived([F { _logger.LogInformation(EventIds.LicenceUpdatedEventPublishedEventReceived.ToEventId(), "ERP Facade webhook has received new licence updated publish event from EES."); - var correlationId = licenceUpdatedEventJson.SelectToken(CorrelationIdKey)?.Value(); + var correlationId = licenceUpdatedEventJson.SelectToken(Constants.CorrelationIdKey)?.Value(); if (string.IsNullOrEmpty(correlationId)) { @@ -199,17 +211,26 @@ public virtual async Task LicenceUpdatedPublishedEventReceived([F return new BadRequestObjectResult(StatusCodes.Status400BadRequest); } + LicenseUpdatedEventEntity licenceUpdatedEventEntity = new() + { + RowKey = Guid.NewGuid().ToString(), + PartitionKey = Guid.NewGuid().ToString(), + Timestamp = DateTime.UtcNow, + CorrelationId = correlationId, + Status = Status.Incomplete.ToString() + }; + _logger.LogInformation(EventIds.StoreLicenceUpdatedPublishedEventInAzureTable.ToEventId(), "Storing the received Licence updated published event in azure table."); - await _azureTableReaderWriter.UpsertLicenceUpdatedEntity(correlationId); + await _azureTableReaderWriter.UpsertEntity(correlationId, Constants.LicenceUpdatedEventTableName, licenceUpdatedEventEntity); _logger.LogInformation(EventIds.UploadLicenceUpdatedPublishedEventInAzureBlob.ToEventId(), "Uploading the received Licence updated published event in blob storage."); - await _azureBlobEventWriter.UploadEvent(licenceUpdatedEventJson.ToString(), LicenceUpdatedContainerName, correlationId + '/' + LicenceUpdatedEventFileName); + await _azureBlobEventWriter.UploadEvent(licenceUpdatedEventJson.ToString(), Constants.LicenceUpdatedEventContainerName, correlationId + '/' + Constants.LicenceUpdatedEventFileName); _logger.LogInformation(EventIds.UploadedLicenceUpdatedPublishedEventInAzureBlob.ToEventId(), "Licence updated published event is uploaded in blob storage successfully."); var sapPayload = _licenceUpdatedSapMessageBuilder.BuildLicenceUpdatedSapMessageXml(JsonConvert.DeserializeObject(licenceUpdatedEventJson.ToString()), correlationId); _logger.LogInformation(EventIds.UploadLicenceUpdatedSapXmlPayloadInAzureBlob.ToEventId(), "Uploading the SAP xml payload for licence updated event in blob storage."); - await _azureBlobEventWriter.UploadEvent(sapPayload.ToIndentedString(), LicenceUpdatedContainerName, correlationId + '/' + SapXmlPayloadFileName); + await _azureBlobEventWriter.UploadEvent(sapPayload.ToIndentedString(), Constants.LicenceUpdatedEventContainerName, correlationId + '/' + Constants.SapXmlPayloadFileName); _logger.LogInformation(EventIds.UploadedLicenceUpdatedSapXmlPayloadInAzureBlob.ToEventId(), "SAP xml payload for licence updated event is uploaded in blob storage successfully."); var response = await _sapClient.PostEventData(sapPayload, _sapConfig.Value.SapEndpointForRecordOfSale, _sapConfig.Value.SapServiceOperationForRecordOfSale, _sapConfig.Value.SapUsernameForRecordOfSale, _sapConfig.Value.SapPasswordForRecordOfSale); @@ -221,7 +242,7 @@ public virtual async Task LicenceUpdatedPublishedEventReceived([F _logger.LogInformation(EventIds.LicenceUpdatedPublishedEventUpdatePushedToSap.ToEventId(), "The licence updated event data has been sent to SAP successfully. | {StatusCode}", response.StatusCode); - await _azureTableReaderWriter.UpdateLicenceUpdatedEventStatus(correlationId); + await _azureTableReaderWriter.UpdateEntity(correlationId, Constants.LicenceUpdatedEventTableName, new[] { new KeyValuePair("Status", Status.Complete.ToString()) }); return new OkObjectResult(StatusCodes.Status200OK); } diff --git a/src/UKHO.ERPFacade.API/Health/HealthResponseWriter.cs b/src/UKHO.ERPFacade.API/Health/HealthResponseWriter.cs index 36c4796b..975d4b5e 100644 --- a/src/UKHO.ERPFacade.API/Health/HealthResponseWriter.cs +++ b/src/UKHO.ERPFacade.API/Health/HealthResponseWriter.cs @@ -3,21 +3,21 @@ using System.Text.Json.Serialization; using System.Text.Unicode; using Microsoft.Extensions.Diagnostics.HealthChecks; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.Health { public static class HealthResponseWriter { - private const string DefaultContentType = "application/json"; private static readonly byte[] _emptyResponse = "{}"u8.ToArray(); private static readonly Lazy _options = new(CreateJsonOptions); - public static async Task WriteHealthCheckUiResponse(HttpContext httpContext, HealthReport report) + public static async Task WriteHealthCheckUiResponse(HttpContext httpContext, HealthReport report) { if (report != null) { - httpContext.Response.ContentType = DefaultContentType; + httpContext.Response.ContentType = Constants.DefaultContentType; ErpHealthReport uiReport = ErpHealthReport.CreateFrom(report); diff --git a/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs b/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs index 0d561b31..e6893565 100644 --- a/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs +++ b/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs @@ -6,7 +6,7 @@ using UKHO.ERPFacade.Common.Providers; using UKHO.ERPFacade.Common.PermitDecryption; using UKHO.ERPFacade.Common.Exceptions; -using System; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.Helpers { @@ -19,44 +19,6 @@ public class EncContentSapMessageBuilder : IEncContentSapMessageBuilder private readonly IWeekDetailsProvider _weekDetailsProvider; private readonly IPermitDecryption _permitDecryption; - private const string SapXmlPath = "SapXmlTemplates\\SAPRequest.xml"; - private const string XpathImMatInfo = $"//*[local-name()='IM_MATINFO']"; - private const string XpathActionItems = $"//*[local-name()='ACTIONITEMS']"; - private const string XpathNoOfActions = $"//*[local-name()='NOOFACTIONS']"; - private const string XpathCorrId = $"//*[local-name()='CORRID']"; - private const string XpathRecDate = $"//*[local-name()='RECDATE']"; - private const string XpathRecTime = $"//*[local-name()='RECTIME']"; - private const string ActionNumber = "ACTIONNUMBER"; - private const string Item = "item"; - private const string Action = "ACTION"; - private const string Product = "PRODUCT"; - private const string ProductSection = "Product"; - private const string ReplacedBy = "REPLACEDBY"; - private const string ChildCell = "CHILDCELL"; - private const string ProdType = "PRODTYPE"; - private const string ProdTypeValue = "S57"; - private const string UnitOfSaleSection = "UnitOfSale"; - private const string UnitSaleType = "unit"; - private const string EncCell = "ENC CELL"; - private const string AvcsUnit = "AVCS UNIT"; - private const string RecDateFormat = "yyyyMMdd"; - private const string RecTimeFormat = "hhmmss"; - private const string UkhoWeekNumberSection = "UkhoWeekNumber"; - private const string ValidFrom = "VALIDFROM"; - private const string WeekNo = "WEEKNO"; - private const string Correction = "CORRECTION"; - private const string IsCorrectionTrue = "Y"; - private const string IsCorrectionFalse = "N"; - private const string ActiveKey = "ACTIVEKEY"; - private const string NextKey = "NEXTKEY"; - private const string UnitOfSaleStatusForSale = "ForSale"; - private const string Agency = "AGENCY"; - private const string CreateEncCell = "CREATE ENC CELL"; - private const string UpdateCell = "UPDATE ENC CELL EDITION UPDATE NUMBER"; - private const string Permit = "permit"; - private const int MaxXmlNodeLength = 250; - private const int MaxAgencyXmlNodeLength = 2; - public EncContentSapMessageBuilder(ILogger logger, IXmlHelper xmlHelper, IFileSystemHelper fileSystemHelper, @@ -80,7 +42,7 @@ IPermitDecryption permitDecryption /// XmlDocument public XmlDocument BuildSapMessageXml(EncEventPayload eventData) { - string sapXmlTemplatePath = Path.Combine(Environment.CurrentDirectory, SapXmlPath); + string sapXmlTemplatePath = Path.Combine(Environment.CurrentDirectory, Constants.S57SapXmlTemplatePath); // Check if SAP XML payload template exists if (!_fileSystemHelper.IsFileExists(sapXmlTemplatePath)) @@ -90,7 +52,7 @@ public XmlDocument BuildSapMessageXml(EncEventPayload eventData) var soapXml = _xmlHelper.CreateXmlDocument(sapXmlTemplatePath); - var actionItemNode = soapXml.SelectSingleNode(XpathActionItems); + var actionItemNode = soapXml.SelectSingleNode(Constants.XpathActionItems); _logger.LogInformation(EventIds.GenerationOfSapXmlPayloadStarted.ToEventId(), "Generation of SAP XML payload started."); @@ -114,7 +76,7 @@ private void BuildEncCellActions(EncEventPayload eventData, XmlDocument soapXml, foreach (var product in eventData.Data.Products) { - foreach (var action in _sapActionConfig.Value.SapActions.Where(x => x.Product == EncCell)) + foreach (var action in _sapActionConfig.Value.SapActions.Where(x => x.Product == Constants.EncCell)) { var unitOfSale = GetUnitOfSale(action.ActionNumber, eventData.Data.UnitsOfSales, product); @@ -164,7 +126,7 @@ private void BuildUnitActions(EncEventPayload eventData, XmlDocument soapXml, Xm { foreach (var unitOfSale in eventData.Data.UnitsOfSales) { - foreach (var action in _sapActionConfig.Value.SapActions.Where(x => x.Product == AvcsUnit)) + foreach (var action in _sapActionConfig.Value.SapActions.Where(x => x.Product == Constants.AvcsUnit)) { if (!ValidateActionRules(action, unitOfSale)) continue; @@ -199,12 +161,12 @@ private void FinalizeSapXmlMessage(XmlDocument soapXml, string correlationId, Xm { var xmlNode = SortXmlPayload(actionItemNode); - SetXmlNodeValue(soapXml, XpathCorrId, correlationId); - SetXmlNodeValue(soapXml, XpathNoOfActions, xmlNode.ChildNodes.Count.ToString()); - SetXmlNodeValue(soapXml, XpathRecDate, DateTime.UtcNow.ToString(RecDateFormat)); - SetXmlNodeValue(soapXml, XpathRecTime, DateTime.UtcNow.ToString(RecTimeFormat)); + SetXmlNodeValue(soapXml, Constants.XpathCorrId, correlationId); + SetXmlNodeValue(soapXml, Constants.XpathNoOfActions, xmlNode.ChildNodes.Count.ToString()); + SetXmlNodeValue(soapXml, Constants.XpathRecDate, DateTime.UtcNow.ToString(Constants.RecDateFormat)); + SetXmlNodeValue(soapXml, Constants.XpathRecTime, DateTime.UtcNow.ToString(Constants.RecTimeFormat)); - var IM_MATINFONode = soapXml.SelectSingleNode(XpathImMatInfo); + var IM_MATINFONode = soapXml.SelectSingleNode(Constants.XpathImMatInfo); IM_MATINFONode.AppendChild(xmlNode); } @@ -220,19 +182,19 @@ private void FinalizeSapXmlMessage(XmlDocument soapXml, string correlationId, Xm return actionNumber switch { //Case 1 : CREATE ENC CELL - 1 => listOfUnitOfSales.FirstOrDefault(x => x.UnitOfSaleType == UnitSaleType && - x.Status == UnitOfSaleStatusForSale && + 1 => listOfUnitOfSales.FirstOrDefault(x => x.UnitOfSaleType == Constants.UnitSaleType && + x.Status == Constants.UnitOfSaleStatusForSale && x.CompositionChanges.AddProducts.Contains(product.ProductName)), //Case 4 : REPLACED WITH ENC CELL //Case 10 : CANCEL ENC CELL - 4 or 10 => listOfUnitOfSales.FirstOrDefault(x => x.UnitOfSaleType == UnitSaleType && + 4 or 10 => listOfUnitOfSales.FirstOrDefault(x => x.UnitOfSaleType == Constants.UnitSaleType && x.CompositionChanges.RemoveProducts.Contains(product.ProductName)), //Case 6 : CHANGE ENC CELL //Case 8 : UPDATE ENC CELL EDITION UPDATE NUMBER - 6 or 8 => listOfUnitOfSales.FirstOrDefault(x => x.UnitOfSaleType == UnitSaleType && - x.Status == UnitOfSaleStatusForSale && + 6 or 8 => listOfUnitOfSales.FirstOrDefault(x => x.UnitOfSaleType == Constants.UnitSaleType && + x.Status == Constants.UnitOfSaleStatusForSale && product.InUnitsOfSale.Contains(x.UnitName)), _ => null, }; @@ -285,33 +247,33 @@ private XmlElement BuildAction(XmlDocument soapXml, Product product, UnitOfSale DecryptedPermit decryptedPermit = null; // Create main item node - var itemNode = soapXml.CreateElement(Item); + var itemNode = soapXml.CreateElement(Constants.Item); // Add basic action-related nodes - AppendChildNode(itemNode, soapXml, ActionNumber, action.ActionNumber.ToString()); - AppendChildNode(itemNode, soapXml, Action, action.Action.ToString()); - AppendChildNode(itemNode, soapXml, Product, action.Product.ToString()); - AppendChildNode(itemNode, soapXml, ProdType, ProdTypeValue); + AppendChildNode(itemNode, soapXml, Constants.ActionNumber, action.ActionNumber.ToString()); + AppendChildNode(itemNode, soapXml, Constants.Action, action.Action.ToString()); + AppendChildNode(itemNode, soapXml, Constants.Product, action.Product.ToString()); + AppendChildNode(itemNode, soapXml, Constants.ProdType, Constants.ProdTypeValue); // Add child cell node - AppendChildNode(itemNode, soapXml, ChildCell, childCell); + AppendChildNode(itemNode, soapXml, Constants.ChildCell, childCell); List<(int sortingOrder, XmlElement node)> actionAttributes = new(); // Get permit keys for New cell and Updated cell - if (action.Action == CreateEncCell || action.Action == UpdateCell) + if (action.Action == Constants.CreateEncCell || action.Action == Constants.UpdateCell) { decryptedPermit = _permitDecryption.Decrypt(product.Permit); } // Process ProductSection attributes - ProcessAttributes(action.Action, action.Attributes.Where(x => x.Section == ProductSection), soapXml, product, actionAttributes, decryptedPermit, replacedBy); + ProcessAttributes(action.Action, action.Attributes.Where(x => x.Section == Constants.ProductSection), soapXml, product, actionAttributes, decryptedPermit, replacedBy); // Process UnitOfSaleSection attributes - ProcessAttributes(action.Action, action.Attributes.Where(x => x.Section == UnitOfSaleSection), soapXml, unitOfSale, actionAttributes, null, null); + ProcessAttributes(action.Action, action.Attributes.Where(x => x.Section == Constants.UnitOfSaleSection), soapXml, unitOfSale, actionAttributes, null, null); // Process UkhoWeekNumberSection attributes - ProcessUkhoWeekNumberAttributes(action.Action, action.Attributes.Where(x => x.Section == UkhoWeekNumberSection), soapXml, ukhoWeekNumber, actionAttributes); + ProcessUkhoWeekNumberAttributes(action.Action, action.Attributes.Where(x => x.Section == Constants.UkhoWeekNumberSection), soapXml, ukhoWeekNumber, actionAttributes); // Sort and append attributes to SAP action foreach (var (sortingOrder, node) in actionAttributes.OrderBy(x => x.sortingOrder)) @@ -341,13 +303,13 @@ private void ProcessAttributes(string action, IEnumerable a { switch (attribute.XmlNodeName) { - case ReplacedBy: + case Constants.ReplacedBy: if (!IsPropertyNullOrEmpty(attribute.JsonPropertyName, replacedBy)) attributeNode.InnerText = GetXmlNodeValue(replacedBy.ToString(), attribute.XmlNodeName); break; - case ActiveKey: + case Constants.ActiveKey: if (!IsPropertyNullOrEmpty(attribute.JsonPropertyName, decryptedPermit.ActiveKey)) attributeNode.InnerText = GetXmlNodeValue(decryptedPermit.ActiveKey, attribute.XmlNodeName); break; - case NextKey: + case Constants.NextKey: if (!IsPropertyNullOrEmpty(attribute.JsonPropertyName, decryptedPermit.NextKey)) attributeNode.InnerText = GetXmlNodeValue(decryptedPermit.NextKey, attribute.XmlNodeName); break; default: @@ -391,16 +353,16 @@ private void ProcessUkhoWeekNumberAttributes(string action, IEnumerable Convert.ToInt32(node.SelectSingleNode(ActionNumber)?.InnerText ?? "0")) + .OrderBy(node => Convert.ToInt32(node.SelectSingleNode(Constants.ActionNumber)?.InnerText ?? "0")) .ToList(); // Update the sequence number in the sorted list foreach (XmlNode actionItem in sortedActionItems) { - var actionNumberNode = actionItem.SelectSingleNode(ActionNumber); + var actionNumberNode = actionItem.SelectSingleNode(Constants.ActionNumber); if (actionNumberNode != null) { actionNumberNode.InnerText = sequenceNumber.ToString(); diff --git a/src/UKHO.ERPFacade.API/Helpers/LicenceUpdatedSapMessageBuilder.cs b/src/UKHO.ERPFacade.API/Helpers/LicenceUpdatedSapMessageBuilder.cs index e3ed0272..42f9afb1 100644 --- a/src/UKHO.ERPFacade.API/Helpers/LicenceUpdatedSapMessageBuilder.cs +++ b/src/UKHO.ERPFacade.API/Helpers/LicenceUpdatedSapMessageBuilder.cs @@ -1,4 +1,5 @@ using System.Xml; +using UKHO.ERPFacade.Common.Constants; using UKHO.ERPFacade.Common.IO; using UKHO.ERPFacade.Common.Logging; using UKHO.ERPFacade.Common.Models; @@ -11,10 +12,6 @@ public class LicenceUpdatedSapMessageBuilder : ILicenceUpdatedSapMessageBuilder private readonly IXmlHelper _xmlHelper; private readonly IFileSystemHelper _fileSystemHelper; - private const string SapXmlPath = "SapXmlTemplates\\RosSapRequest.xml"; - private const string XpathZAddsRos = $"//*[local-name()='Z_ADDS_ROS']"; - private const string ImOrderNameSpace = "RecordOfSale"; - public LicenceUpdatedSapMessageBuilder(ILogger logger, IXmlHelper xmlHelper, IFileSystemHelper fileSystemHelper @@ -27,7 +24,7 @@ IFileSystemHelper fileSystemHelper public XmlDocument BuildLicenceUpdatedSapMessageXml(LicenceUpdatedEventPayLoad eventData, string correlationId) { - string sapXmlTemplatePath = Path.Combine(Environment.CurrentDirectory, SapXmlPath); + string sapXmlTemplatePath = Path.Combine(Environment.CurrentDirectory, Constants.RecordOfSaleSapXmlTemplatePath); if (!_fileSystemHelper.IsFileExists(sapXmlTemplatePath)) { @@ -43,9 +40,9 @@ public XmlDocument BuildLicenceUpdatedSapMessageXml(LicenceUpdatedEventPayLoad e string xml = _xmlHelper.CreateXmlPayLoad(sapRecordOfSalePayLoad); - string sapXml = xml.Replace(ImOrderNameSpace, ""); + string sapXml = xml.Replace(Constants.ImOrderNameSpace, ""); - soapXml.SelectSingleNode(XpathZAddsRos).InnerXml = sapXml.RemoveNullFields().SetXmlClosingTags(); + soapXml.SelectSingleNode(Constants.XpathZAddsRos).InnerXml = sapXml.RemoveNullFields().SetXmlClosingTags(); _logger.LogInformation(EventIds.CreatedLicenceUpdatedSapPayload.ToEventId(), "Licence updated SAP payload created."); diff --git a/src/UKHO.ERPFacade.API/SapXmlTemplates/RosSapRequest.xml b/src/UKHO.ERPFacade.API/SapXmlTemplates/SAPRoSRequest.xml similarity index 100% rename from src/UKHO.ERPFacade.API/SapXmlTemplates/RosSapRequest.xml rename to src/UKHO.ERPFacade.API/SapXmlTemplates/SAPRoSRequest.xml diff --git a/src/UKHO.ERPFacade.API/SapXmlTemplates/SAPRequest.xml b/src/UKHO.ERPFacade.API/SapXmlTemplates/SAPS57Request.xml similarity index 100% rename from src/UKHO.ERPFacade.API/SapXmlTemplates/SAPRequest.xml rename to src/UKHO.ERPFacade.API/SapXmlTemplates/SAPS57Request.xml diff --git a/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj b/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj index d5e95c91..9afae35f 100644 --- a/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj +++ b/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj @@ -55,10 +55,10 @@ - + Always - + Always diff --git a/src/UKHO.ERPFacade.CleanUp.WebJob/Services/CleanUpService.cs b/src/UKHO.ERPFacade.CleanUp.WebJob/Services/CleanUpService.cs index e1733ef4..45f1dfe2 100644 --- a/src/UKHO.ERPFacade.CleanUp.WebJob/Services/CleanUpService.cs +++ b/src/UKHO.ERPFacade.CleanUp.WebJob/Services/CleanUpService.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using UKHO.ERPFacade.Common.Configuration; +using UKHO.ERPFacade.Common.Constants; using UKHO.ERPFacade.Common.IO.Azure; using UKHO.ERPFacade.Common.Logging; @@ -11,7 +12,7 @@ public class CleanUpService : ICleanUpService private readonly ILogger _logger; private readonly IOptions _erpFacadeWebjobConfig; private readonly IAzureTableReaderWriter _azureTableReaderWriter; - private readonly IAzureBlobEventWriter _azureBlobEventWriter; + private readonly IAzureBlobEventWriter _azureBlobEventWriter; public CleanUpService(ILogger logger, IOptions erpFacadeWebjobConfig, @@ -25,25 +26,30 @@ public CleanUpService(ILogger logger, } public void CleanUpAzureTableAndBlobs() - { - CleanUpBlobsAndTablesRelatedToEESEvent(); + { + CleanUpEvents(Constants.S57EventTableName, Constants.S57EventContainerName); } - //Private methods - private void CleanUpBlobsAndTablesRelatedToEESEvent() + private void CleanUpEvents(string tableName, string eventContainerName) { - _logger.LogInformation(EventIds.FetchEESEntities.ToEventId(), "Fetching all EES entities from azure table"); - var entities = _azureTableReaderWriter.GetAllEntityForEESTable(); + _logger.LogInformation(EventIds.FetchEESEntities.ToEventId(), "Fetching all records from azure table {TableName}", tableName); + + var entities = _azureTableReaderWriter.GetAllEntities(tableName); + foreach (var entity in entities) { - if (!entity.RequestDateTime.HasValue) + if (entity["RequestDateTime"] == null) continue; - TimeSpan timediff = DateTime.Now - entity.RequestDateTime.Value; + + TimeSpan timediff = DateTime.Now - Convert.ToDateTime(entity["RequestDateTime"].ToString()); + if (timediff.Days > int.Parse(_erpFacadeWebjobConfig.Value.CleanUpDurationInDays)) { - Task.FromResult(_azureTableReaderWriter.DeleteEESEntity(entity.CorrelationId)); - _logger.LogInformation(EventIds.DeletedContainerSuccessful.ToEventId(), "Deleting container : {0}", entity.CorrelationId); - _azureBlobEventWriter.DeleteContainer(entity.CorrelationId.ToLower()); + Task.FromResult(_azureTableReaderWriter.DeleteEntity(entity["CorrelationId"].ToString(), tableName)); + + _logger.LogInformation(EventIds.DeletedContainerSuccessful.ToEventId(), "Deleting directory {CorrelationId} from {EventContainerName} container", entity["CorrelationId"].ToString(), eventContainerName); + + _azureBlobEventWriter.DeleteDirectory(eventContainerName, entity["CorrelationId"].ToString().ToLower()); } } } diff --git a/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj b/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj index a15b921e..1da22d2c 100644 --- a/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj +++ b/src/UKHO.ERPFacade.CleanUp.WebJob/UKHO.ERPFacade.CleanUp.WebJob.csproj @@ -50,9 +50,6 @@ - - Never - Always diff --git a/src/UKHO.ERPFacade.Common/Constants/Constants.cs b/src/UKHO.ERPFacade.Common/Constants/Constants.cs new file mode 100644 index 00000000..74978679 --- /dev/null +++ b/src/UKHO.ERPFacade.Common/Constants/Constants.cs @@ -0,0 +1,145 @@ +using System.Diagnostics.CodeAnalysis; + +namespace UKHO.ERPFacade.Common.Constants +{ + [ExcludeFromCodeCoverage] + public static class Constants + { + //JSON field keys + public const string EventIdKey = "id"; + public const string DataNode = "data"; + public const string CorrelationIdKey = "data.correlationId"; + public const string ProductsNode = "data.products"; + public const string UnitsOfSaleNode = "data.unitsOfSale"; + public const string UKHOWeekNumber = "data.ukhoWeekNumber"; + + + //SAP xml payload file name + public const string SapXmlPayloadFileName = "SapXmlPayload.xml"; + + //S57 event file name + public const string S57EncEventFileName = "EncPublishingEvent.json"; + + //S57 event storage + public const string S57EventTableName = "encevents"; + public const string S57EventContainerName = "s57events"; + public const string ErpFacadeExpectedXmlFiles = "ERPFacadeExpectedXmlFiles"; + + //LicenceUpdated event file name + public const string LicenceUpdatedEventFileName = "LicenceUpdatedEvent.json"; + + //LicenceUpdated event storage + public const string LicenceUpdatedEventTableName = "licenceupdatedevents"; + public const string LicenceUpdatedEventContainerName = "licenceupdatedblobs"; + + //RecordOfSale event storage + public const string RecordOfSaleQueueName = "recordofsaleevents"; + public const string RecordOfSaleEventTableName = "recordofsaleevents"; + public const string RecordOfSaleEventContainerName = "recordofsaleblobs"; + public const string RecordOfSaleEventFileExtension = ".json"; + + //S57 xml template xpath + public const string S57SapXmlTemplatePath = "SapXmlTemplates\\SAPS57Request.xml"; + public const string XpathImMatInfo = $"//*[local-name()='IM_MATINFO']"; + public const string XpathActionItems = $"//*[local-name()='ACTIONITEMS']"; + public const string XpathNoOfActions = $"//*[local-name()='NOOFACTIONS']"; + public const string XpathCorrId = $"//*[local-name()='CORRID']"; + public const string XpathRecDate = $"//*[local-name()='RECDATE']"; + public const string XpathRecTime = $"//*[local-name()='RECTIME']"; + public const string Item = "item"; + + //S57 xml payload basic nodes + public const string ActionNumber = "ACTIONNUMBER"; + public const string Action = "ACTION"; + public const string Product = "PRODUCT"; + public const string ProdType = "PRODTYPE"; + public const string ReplacedBy = "REPLACEDBY"; + public const string ChildCell = "CHILDCELL"; + public const string RecDateFormat = "yyyyMMdd"; + public const string RecTimeFormat = "hhmmss"; + + public const string EncCell = "ENC CELL"; + public const string AvcsUnit = "AVCS UNIT"; + + public const string ProductSection = "Product"; + public const string ProdTypeValue = "S57"; + public const string Permit = "permit"; + + public const string UnitOfSaleSection = "UnitOfSale"; + public const string UnitSaleType = "unit"; + public const string UnitOfSaleStatusForSale = "ForSale"; + public const string Products = "products"; + public const string UnitsOfSale = "unitsOfSale"; + + public const string UkhoWeekNumberSection = "UkhoWeekNumber"; + public const string ValidFrom = "VALIDFROM"; + public const string WeekNo = "WEEKNO"; + public const string Correction = "CORRECTION"; + public const string IsCorrectionTrue = "Y"; + public const string IsCorrectionFalse = "N"; + public const string ActiveKey = "ACTIVEKEY"; + public const string NextKey = "NEXTKEY"; + public const string Agency = "AGENCY"; + + public const string CreateEncCell = "CREATE ENC CELL"; + public const string UpdateCell = "UPDATE ENC CELL EDITION UPDATE NUMBER"; + + public const int MaxXmlNodeLength = 250; + public const int MaxAgencyXmlNodeLength = 2; + + + //RecordOfSale xml payload builder + public const string RecordOfSaleSapXmlTemplatePath = "SapXmlTemplates\\SAPRoSRequest.xml"; + public const string XpathZAddsRos = $"//*[local-name()='Z_ADDS_ROS']"; + public const string ImOrderNameSpace = "RecordOfSale"; + public const string MaintainHoldingsType = "MAINTAINHOLDINGS"; + public const string NewLicenceType = "NEWLICENCE"; + public const string MigrateNewLicenceType = "MIGRATENEWLICENCE"; + public const string MigrateExistingLicenceType = "MIGRATEEXISTINGLICENCE"; + public const string ConvertLicenceType = "CONVERTLICENCE"; + + public const string S57RequestEndPoint = "/webhook/newenccontentpublishedeventreceived"; + public const string LicenceUpdatedRequestEndPoint = "/webhook/licenceupdatedpublishedeventreceived"; + public const string RoSWebhookRequestEndPoint = "/webhook/recordofsalepublishedeventreceived"; + + public const string SapHealthCheckXmlPath = "SapXmlTemplates\\SAPHealthCheckRequest.xml"; + public const string DefaultContentType = "application/json"; + public const string RosPayloadTestDataFolder = "RoSPayloadTestData"; + + public const string SoldToAcc = "SOLDTOACC"; + public const string LicenceAcc = "LICENSEEACC"; + public const string StartDate = "STARTDATE"; + public const string EndDate = "ENDDATE"; + public const string VName = "VNAME"; + public const string Imo = "IMO"; + public const string CallSign = "CALLSIGN"; + public const string ShoreBased = "SHOREBASED"; + public const string Fleet = "FLEET"; + public const string Users = "USERS"; + public const string EndUserId = "ENDUSERID"; + public const string EcdisManUf = "ECDISMANUF"; + public const string LType = "LTYPE"; + public const string LicDur = "LICDUR"; + public const string LicNo = "LICNO"; + public const string Repeat = "REPEAT"; + public const string ProductOrder = "PO"; + public const string AdsOrderNumber = "ADSORDNO"; + public const string Id = "ID"; + public const string ProductEndDate = "ENDDA"; + public const string Duration = "DURATION"; + public const string Renew = "RENEW"; + public const string SoapEnvelope = "soap:Envelope"; + public const string SoapBody = "soap:Body"; + + //Functional Tests + public const string XpathActionNumber = $"//*[local-name()='ACTIONNUMBER']"; + public const string XpathAction = $"//*[local-name()='ACTION']"; + public const string ReplaceEncCellAction = "REPLACED WITH ENC CELL"; + public const string ChangeEncCellAction = "CHANGE ENC CELL"; + public const string PermitWithSameKey = "PermitWithSameKey"; + public const string PermitWithDifferentKey = "PermitWithDifferentKey"; + + //LicenseUpdate xml payload nodes + public const string LicTransaction = "CHANGELICENCE"; + } +} diff --git a/src/UKHO.ERPFacade.Common/Enums/Status.cs b/src/UKHO.ERPFacade.Common/Enums/Status.cs new file mode 100644 index 00000000..6fc8d962 --- /dev/null +++ b/src/UKHO.ERPFacade.Common/Enums/Status.cs @@ -0,0 +1,8 @@ +namespace UKHO.ERPFacade.Common.Enums +{ + public enum Status + { + Incomplete, + Complete + } +} diff --git a/src/UKHO.ERPFacade.Common/IO/Azure/AzureBlobEventWriter.cs b/src/UKHO.ERPFacade.Common/IO/Azure/AzureBlobEventWriter.cs index d5d7f6ed..b2387c05 100644 --- a/src/UKHO.ERPFacade.Common/IO/Azure/AzureBlobEventWriter.cs +++ b/src/UKHO.ERPFacade.Common/IO/Azure/AzureBlobEventWriter.cs @@ -67,6 +67,21 @@ public bool DeleteContainer(string blobContainerName) return blobContainerClient.DeleteIfExists(); } + public bool DeleteDirectory(string blobContainerName, string directoryName) + { + BlobContainerClient blobContainerClient = new(_azureStorageConfig.Value.ConnectionString, blobContainerName); + + // List all blobs with the directory prefix + foreach (var blobItem in blobContainerClient.GetBlobs(prefix: directoryName)) + { + // Get the BlobClient for each blob and delete it + BlobClient blobClient = blobContainerClient.GetBlobClient(blobItem.Name); + Console.WriteLine($"Deleting blob: {blobItem.Name}"); + blobClient.DeleteIfExists(); + } + return true; + } + public List GetBlobNamesInFolder(string blobContainerName, string corrId) { List blobList = new(); diff --git a/src/UKHO.ERPFacade.Common/IO/Azure/AzureQueueHelper.cs b/src/UKHO.ERPFacade.Common/IO/Azure/AzureQueueHelper.cs index 073058ee..cc9a2f40 100644 --- a/src/UKHO.ERPFacade.Common/IO/Azure/AzureQueueHelper.cs +++ b/src/UKHO.ERPFacade.Common/IO/Azure/AzureQueueHelper.cs @@ -13,7 +13,6 @@ namespace UKHO.ERPFacade.Common.IO.Azure public class AzureQueueHelper : IAzureQueueHelper { private readonly IOptions _azureStorageConfig; - private const string RecordOfSaleQueueName = "recordofsaleevents"; public AzureQueueHelper(IOptions azureStorageConfig) { @@ -25,7 +24,7 @@ public async Task AddMessage(JObject rosEventJson) var rosEventData = JsonConvert.DeserializeObject(rosEventJson.ToString()); string queueMessage = BuildQueueMessage(rosEventData); - QueueClient queueClient = GetQueueClient(RecordOfSaleQueueName); + QueueClient queueClient = GetQueueClient(Constants.Constants.RecordOfSaleQueueName); await queueClient.SendMessageAsync(queueMessage); } diff --git a/src/UKHO.ERPFacade.Common/IO/Azure/AzureTableReaderWriter.cs b/src/UKHO.ERPFacade.Common/IO/Azure/AzureTableReaderWriter.cs index 48c46b9e..937d5795 100644 --- a/src/UKHO.ERPFacade.Common/IO/Azure/AzureTableReaderWriter.cs +++ b/src/UKHO.ERPFacade.Common/IO/Azure/AzureTableReaderWriter.cs @@ -6,7 +6,6 @@ using Microsoft.Extensions.Options; using UKHO.ERPFacade.Common.Configuration; using UKHO.ERPFacade.Common.Logging; -using UKHO.ERPFacade.Common.Models.TableEntities; namespace UKHO.ERPFacade.Common.IO.Azure { @@ -15,95 +14,37 @@ public class AzureTableReaderWriter : IAzureTableReaderWriter { private readonly ILogger _logger; private readonly IOptions _azureStorageConfig; - private const string ErpFacadeTableName = "encevents"; - private const string LicenceUpdateTableName = "licenceupdatedevents"; - private const string RecordOfSaleTableName = "recordofsaleevents"; - - private enum Statuses - { - Incomplete, - Complete - } public AzureTableReaderWriter(ILogger logger, - IOptions azureStorageConfig, - IOptions erpFacadeWebjobConfig) + IOptions azureStorageConfig) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _azureStorageConfig = azureStorageConfig ?? throw new ArgumentNullException(nameof(azureStorageConfig)); } - public async Task UpsertEntity(string correlationId) - { - TableClient tableClient = GetTableClient(ErpFacadeTableName); - - EESEventEntity existingEntity = await GetEntity(correlationId); - - if (existingEntity == null!) - { - EESEventEntity eESEvent = new() - { - RowKey = Guid.NewGuid().ToString(), - PartitionKey = Guid.NewGuid().ToString(), - Timestamp = DateTime.UtcNow, - CorrelationId = correlationId, - RequestDateTime = null - }; - - await tableClient.AddEntityAsync(eESEvent, CancellationToken.None); - - _logger.LogInformation(EventIds.AddedEntryForEncContentPublishedEventInAzureTable.ToEventId(), "New enccontentpublished event entry is added in azure table successfully."); - } - else - { - _logger.LogWarning(EventIds.ReceivedDuplicateEncContentPublishedEvent.ToEventId(), "Duplicate enccontentpublished event received."); - - existingEntity.Timestamp = DateTime.UtcNow; - - await tableClient.UpdateEntityAsync(existingEntity, ETag.All, TableUpdateMode.Replace); - - _logger.LogInformation(EventIds.UpdatedEncContentPublishedEventInAzureTable.ToEventId(), "Existing enccontentpublished event entry is updated in azure table successfully."); - } - } - - public async Task UpsertLicenceUpdatedEntity(string correlationId) + public async Task UpsertEntity(string correlationId, string tableName, ITableEntity entity) { - TableClient tableClient = GetTableClient(LicenceUpdateTableName); + TableClient tableClient = GetTableClient(tableName); - var existingEntity = await GetRecordOfSaleEntity(correlationId, LicenceUpdateTableName); + TableEntity existingEntity = await GetEntity(correlationId, tableName); if (existingEntity == null!) { - RecordOfSaleEventEntity licenceUpdatedEventsEntity = new() - { - RowKey = Guid.NewGuid().ToString(), - PartitionKey = Guid.NewGuid().ToString(), - Timestamp = DateTime.UtcNow, - CorrelationId = correlationId, - Status = Statuses.Incomplete.ToString() - }; - - await tableClient.AddEntityAsync(licenceUpdatedEventsEntity, CancellationToken.None); - - _logger.LogInformation(EventIds.AddedLicenceUpdatedPublishedEventInAzureTable.ToEventId(), "Licence updated published event is added in azure table successfully."); + await tableClient.AddEntityAsync(entity, CancellationToken.None); } else { - _logger.LogWarning(EventIds.ReceivedDuplicateLicenceUpdatedPublishedEvent.ToEventId(), "Duplicate Licence updated published event received."); - existingEntity.Timestamp = DateTime.UtcNow; await tableClient.UpdateEntityAsync(existingEntity, ETag.All, TableUpdateMode.Replace); - - _logger.LogInformation(EventIds.UpdatedLicenceUpdatedPublishedEventInAzureTable.ToEventId(), "Existing Licence updated published event is updated in azure table successfully."); } } - public async Task GetEntity(string correlationId) + public async Task GetEntity(string correlationId, string tableName) { - IList records = new List(); - TableClient tableClient = GetTableClient(ErpFacadeTableName); - var entities = tableClient.QueryAsync(filter: TableClient.CreateQueryFilter($"CorrelationId eq {correlationId}"), maxPerPage: 1); + IList records = new List(); + TableClient tableClient = GetTableClient(tableName); + var entities = tableClient.QueryAsync(filter: TableClient.CreateQueryFilter($"CorrelationId eq {correlationId}"), maxPerPage: 1); await foreach (var entity in entities) { records.Add(entity); @@ -111,23 +52,25 @@ public async Task GetEntity(string correlationId) return records.FirstOrDefault(); } - public async Task UpdateRequestTimeEntity(string correlationId) + public async Task UpdateEntity(string correlationId, string tableName, KeyValuePair[] entitiesToUpdate) { - TableClient tableClient = GetTableClient(ErpFacadeTableName); - EESEventEntity existingEntity = await GetEntity(correlationId); + TableClient tableClient = GetTableClient(tableName); + TableEntity existingEntity = await GetEntity(correlationId, tableName); if (existingEntity != null) { - existingEntity.RequestDateTime = DateTime.UtcNow; + foreach (var entity in entitiesToUpdate) + { + existingEntity[entity.Key.ToString()] = entity.Value; + } await tableClient.UpdateEntityAsync(existingEntity, ETag.All, TableUpdateMode.Replace); - _logger.LogInformation(EventIds.UpdateRequestTimeEntitySuccessful.ToEventId(), "SAP request time for {CorrelationId} is updated in azure table successfully.", correlationId); } } - public IList GetAllEntityForEESTable() + public IList GetAllEntities(string tableName) { - IList records = new List(); - TableClient tableClient = GetTableClient(ErpFacadeTableName); - var entities = tableClient.Query(); + var records = new List(); + TableClient tableClient = GetTableClient(tableName); + var entities = tableClient.Query(); foreach (var entity in entities) { records.Add(entity); @@ -135,10 +78,10 @@ public IList GetAllEntityForEESTable() return records; } - public async Task DeleteEESEntity(string correlationId) + public async Task DeleteEntity(string correlationId, string tableName) { - TableClient tableClient = GetTableClient(ErpFacadeTableName); - EESEventEntity existingEntity = await GetEntity(correlationId); + TableClient tableClient = GetTableClient(tableName); + TableEntity existingEntity = await GetEntity(correlationId, tableName); if (existingEntity != null) { tableClient.DeleteEntity(existingEntity.PartitionKey, existingEntity.RowKey); @@ -146,95 +89,6 @@ public async Task DeleteEESEntity(string correlationId) } } - public async Task UpsertRecordOfSaleEntity(string correlationId) - { - TableClient tableClient = GetTableClient(RecordOfSaleTableName); - - RecordOfSaleEventEntity existingEntity = await GetRecordOfSaleEntity(correlationId, RecordOfSaleTableName); - - if (existingEntity == null!) - { - RecordOfSaleEventEntity recordOfSaleEvent = new() - { - RowKey = Guid.NewGuid().ToString(), - PartitionKey = Guid.NewGuid().ToString(), - Timestamp = DateTime.UtcNow, - CorrelationId = correlationId, - Status = Statuses.Incomplete.ToString() - }; - - await tableClient.AddEntityAsync(recordOfSaleEvent, CancellationToken.None); - - _logger.LogInformation(EventIds.AddedRecordOfSalePublishedEventInAzureTable.ToEventId(), "Record Of Sale published event is added in azure table successfully."); - } - else - { - _logger.LogWarning(EventIds.ReceivedDuplicateRecordOfSalePublishedEvent.ToEventId(), "Duplicate record of sale published event received."); - - existingEntity.Timestamp = DateTime.UtcNow; - - await tableClient.UpdateEntityAsync(existingEntity, ETag.All, TableUpdateMode.Replace); - - _logger.LogInformation(EventIds.UpdatedRecordOfSalePublishedEventInAzureTable.ToEventId(), "Existing Record Of Sale published event is updated in azure table successfully."); - } - } - - public async Task GetRecordOfSaleEntity(string correlationId, string tableName) - { - IList records = new List(); - TableClient tableClient = GetTableClient(tableName); - var entities = tableClient.QueryAsync(filter: TableClient.CreateQueryFilter($"CorrelationId eq {correlationId}"), maxPerPage: 1); - await foreach (var entity in entities) - { - records.Add(entity); - } - return records.FirstOrDefault(); - } - - public async Task UpdateRecordOfSaleEventStatus(string correlationId) - { - TableClient tableClient = GetTableClient(RecordOfSaleTableName); - RecordOfSaleEventEntity existingEntity = await GetRecordOfSaleEntity(correlationId, RecordOfSaleTableName); - - if (existingEntity != null!) - { - existingEntity.Status = Statuses.Complete.ToString(); - await tableClient.UpdateEntityAsync(existingEntity, ETag.All, TableUpdateMode.Replace); - - _logger.LogInformation(EventIds.UpdatedStatusOfRecordOfSalePublishedEventInAzureTable.ToEventId(), "Status of existing record of sale published event updated in azure table successfully."); - } - } - - public async Task UpdateLicenceUpdatedEventStatus(string correlationId) - { - TableClient tableClient = GetTableClient(LicenceUpdateTableName); - RecordOfSaleEventEntity existingEntity = await GetRecordOfSaleEntity(correlationId, LicenceUpdateTableName); - - if (existingEntity != null!) - { - existingEntity.Status = Statuses.Complete.ToString(); - await tableClient.UpdateEntityAsync(existingEntity, ETag.All, TableUpdateMode.Replace); - - _logger.LogInformation(EventIds.UpdatedStatusOfLicenceUpdatedPublishedEventInAzureTable.ToEventId(), "Status of existing licence updated published event updated in azure table successfully."); - } - } - - public string GetEntityStatus(string correlationId) - { - string status = string.Empty; - ; - TableClient tableClient = GetTableClient(RecordOfSaleTableName); - - var entities = tableClient.Query(filter: TableClient.CreateQueryFilter($"CorrelationId eq {correlationId}"), maxPerPage: 1); - - foreach (var entity in entities) - { - status = entity.Status; - } - - return status; - } - //Private Methods private TableClient GetTableClient(string tableName) { diff --git a/src/UKHO.ERPFacade.Common/IO/Azure/IAzureBlobEventWriter.cs b/src/UKHO.ERPFacade.Common/IO/Azure/IAzureBlobEventWriter.cs index a55eeaae..354f62c7 100644 --- a/src/UKHO.ERPFacade.Common/IO/Azure/IAzureBlobEventWriter.cs +++ b/src/UKHO.ERPFacade.Common/IO/Azure/IAzureBlobEventWriter.cs @@ -3,19 +3,13 @@ public interface IAzureBlobEventWriter { Task UploadEvent(string requestEvent, string blobContainerName, string blobName); - bool CheckIfContainerExists(string containerName); - string DownloadEvent(string blobName, string blobContainerName); - DateTime GetBlobCreateDate(string blobName, string blobContainerName); - IEnumerable GetBlobsInContainer(string blobContainerName, string corrId); - bool DeleteBlob(string blobName, string blobContainerName); - bool DeleteContainer(string blobContainerName); - + bool DeleteDirectory(string blobContainerName, string directoryName); List GetBlobNamesInFolder(string blobContainerName, string corrId); } } diff --git a/src/UKHO.ERPFacade.Common/IO/Azure/IAzureTableReaderWriter.cs b/src/UKHO.ERPFacade.Common/IO/Azure/IAzureTableReaderWriter.cs index 550c4300..2298970e 100644 --- a/src/UKHO.ERPFacade.Common/IO/Azure/IAzureTableReaderWriter.cs +++ b/src/UKHO.ERPFacade.Common/IO/Azure/IAzureTableReaderWriter.cs @@ -1,19 +1,13 @@ -using UKHO.ERPFacade.Common.Models.TableEntities; +using Azure.Data.Tables; namespace UKHO.ERPFacade.Common.IO.Azure { public interface IAzureTableReaderWriter { - Task UpsertEntity(string correlationId); - Task UpsertLicenceUpdatedEntity(string correlationId); - Task GetEntity(string correlationId); - Task UpdateRequestTimeEntity(string correlationId); - IList GetAllEntityForEESTable(); - Task DeleteEESEntity(string correlationId); - Task UpsertRecordOfSaleEntity(string correlationId); - Task GetRecordOfSaleEntity(string correlationId, string tableName); - Task UpdateRecordOfSaleEventStatus(string correlationId); - Task UpdateLicenceUpdatedEventStatus(string correlationId); - string GetEntityStatus(string correlationId); + Task UpsertEntity(string correlationId, string tableName, ITableEntity entity); + Task UpdateEntity(string correlationId, string tableName, KeyValuePair[] entitiesToUpdate); + IList GetAllEntities(string tableName); + Task DeleteEntity(string correlationId, string tableName); + Task GetEntity(string correlationId, string tableName); } } diff --git a/src/UKHO.ERPFacade.Common/Models/TableEntities/EESEventEntity.cs b/src/UKHO.ERPFacade.Common/Models/TableEntities/EncEventEntity.cs similarity index 92% rename from src/UKHO.ERPFacade.Common/Models/TableEntities/EESEventEntity.cs rename to src/UKHO.ERPFacade.Common/Models/TableEntities/EncEventEntity.cs index 2860985a..f3ccdddd 100644 --- a/src/UKHO.ERPFacade.Common/Models/TableEntities/EESEventEntity.cs +++ b/src/UKHO.ERPFacade.Common/Models/TableEntities/EncEventEntity.cs @@ -5,7 +5,7 @@ namespace UKHO.ERPFacade.Common.Models.TableEntities { [ExcludeFromCodeCoverage] - public class EESEventEntity : ITableEntity + public class EncEventEntity : ITableEntity { public string RowKey { get; set; } = default!; diff --git a/src/UKHO.ERPFacade.Common/Models/TableEntities/LicenseUpdatedEventEntity.cs b/src/UKHO.ERPFacade.Common/Models/TableEntities/LicenseUpdatedEventEntity.cs new file mode 100644 index 00000000..98dd1a0c --- /dev/null +++ b/src/UKHO.ERPFacade.Common/Models/TableEntities/LicenseUpdatedEventEntity.cs @@ -0,0 +1,22 @@ +using System.Diagnostics.CodeAnalysis; +using Azure; +using Azure.Data.Tables; + +namespace UKHO.ERPFacade.Common.Models.TableEntities +{ + [ExcludeFromCodeCoverage] + public class LicenseUpdatedEventEntity : ITableEntity + { + public string RowKey { get; set; } = default!; + + public string PartitionKey { get; set; } = default!; + + public DateTimeOffset? Timestamp { get; set; } = default!; + + public string CorrelationId { get; set; } = default!; + + public string Status { get; set; } = default!; + + public ETag ETag { get; set; } = default!; + } +} diff --git a/src/UKHO.ERPFacade.EventAggregation.WebJob/EventAggregationWebjob.cs b/src/UKHO.ERPFacade.EventAggregation.WebJob/EventAggregationWebjob.cs index c08bc6d3..0cb922c4 100644 --- a/src/UKHO.ERPFacade.EventAggregation.WebJob/EventAggregationWebjob.cs +++ b/src/UKHO.ERPFacade.EventAggregation.WebJob/EventAggregationWebjob.cs @@ -2,6 +2,7 @@ using Azure.Storage.Queues.Models; using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; +using UKHO.ERPFacade.Common.Constants; using UKHO.ERPFacade.Common.Logging; using UKHO.ERPFacade.EventAggregation.WebJob.Services; @@ -12,7 +13,6 @@ public class EventAggregationWebjob { private readonly ILogger _logger; private readonly IAggregationService _aggregationService; - private const string RecordOfSaleQueueName = "recordofsaleevents"; public EventAggregationWebjob(ILogger logger, IAggregationService aggregationService) { @@ -20,7 +20,7 @@ public EventAggregationWebjob(ILogger logger, IAggregati _aggregationService = aggregationService ?? throw new ArgumentNullException(nameof(aggregationService)); } - public async Task ProcessQueueMessage([QueueTrigger(RecordOfSaleQueueName)] QueueMessage message) + public async Task ProcessQueueMessage([QueueTrigger(Constants.RecordOfSaleQueueName)] QueueMessage message) { _logger.LogInformation(EventIds.WebjobForEventAggregationStarted.ToEventId(), "Webjob has started to process and merge sliced events."); await _aggregationService.MergeRecordOfSaleEvents(message); diff --git a/src/UKHO.ERPFacade.EventAggregation.WebJob/Helpers/RecordOfSaleSapMessageBuilder.cs b/src/UKHO.ERPFacade.EventAggregation.WebJob/Helpers/RecordOfSaleSapMessageBuilder.cs index fabf19a9..4bd5db6a 100644 --- a/src/UKHO.ERPFacade.EventAggregation.WebJob/Helpers/RecordOfSaleSapMessageBuilder.cs +++ b/src/UKHO.ERPFacade.EventAggregation.WebJob/Helpers/RecordOfSaleSapMessageBuilder.cs @@ -1,5 +1,6 @@ using System.Xml; using Microsoft.Extensions.Logging; +using UKHO.ERPFacade.Common.Constants; using UKHO.ERPFacade.Common.IO; using UKHO.ERPFacade.Common.Logging; using UKHO.ERPFacade.Common.Models; @@ -12,15 +13,6 @@ public class RecordOfSaleSapMessageBuilder : IRecordOfSaleSapMessageBuilder private readonly IXmlHelper _xmlHelper; private readonly IFileSystemHelper _fileSystemHelper; - private const string SapXmlPath = "SapXmlTemplates\\RosSapRequest.xml"; - private const string XpathZAddsRos = $"//*[local-name()='Z_ADDS_ROS']"; - private const string ImOrderNameSpace = "RecordOfSale"; - private const string MaintainHoldingsType = "MAINTAINHOLDINGS"; - private const string NewLicenceType = "NEWLICENCE"; - private const string MigrateNewLicenceType = "MIGRATENEWLICENCE"; - private const string MigrateExistingLicenceType = "MIGRATEEXISTINGLICENCE"; - private const string ConvertLicenceType = "CONVERTLICENCE"; - public RecordOfSaleSapMessageBuilder(ILogger logger, IXmlHelper xmlHelper, IFileSystemHelper fileSystemHelper @@ -35,7 +27,7 @@ public XmlDocument BuildRecordOfSaleSapMessageXml(List { SapRecordOfSalePayLoad sapRecordOfSalePayLoad = null!; - string sapXmlTemplatePath = Path.Combine(Environment.CurrentDirectory, SapXmlPath); + string sapXmlTemplatePath = Path.Combine(Environment.CurrentDirectory, Constants.RecordOfSaleSapXmlTemplatePath); if (!_fileSystemHelper.IsFileExists(sapXmlTemplatePath)) { @@ -49,19 +41,19 @@ public XmlDocument BuildRecordOfSaleSapMessageXml(List sapRecordOfSalePayLoad = eventDataList[0].Data.RecordsOfSale.TransactionType switch { - NewLicenceType => BuildNewLicencePayload(eventDataList), - MaintainHoldingsType => BuildMaintainHoldingsPayload(eventDataList), - MigrateNewLicenceType => BuildMigrateNewLicencePayload(eventDataList), - MigrateExistingLicenceType => BuildMigrateExistingLicencePayload(eventDataList), - ConvertLicenceType => BuildConvertLicencePayload(eventDataList), + Constants.NewLicenceType => BuildNewLicencePayload(eventDataList), + Constants.MigrateNewLicenceType => BuildMigrateNewLicencePayload(eventDataList), + Constants.MigrateExistingLicenceType => BuildMigrateExistingLicencePayload(eventDataList), + Constants.ConvertLicenceType => BuildConvertLicencePayload(eventDataList), + Constants.MaintainHoldingsType => BuildMaintainHoldingsPayload(eventDataList), _ => sapRecordOfSalePayLoad }; string xml = _xmlHelper.CreateXmlPayLoad(sapRecordOfSalePayLoad); - string sapXml = xml.Replace(ImOrderNameSpace, ""); + string sapXml = xml.Replace(Constants.ImOrderNameSpace, ""); - soapXml.SelectSingleNode(XpathZAddsRos)!.InnerXml = sapXml.RemoveNullFields().SetXmlClosingTags(); + soapXml.SelectSingleNode(Constants.XpathZAddsRos)!.InnerXml = sapXml.RemoveNullFields().SetXmlClosingTags(); _logger.LogInformation(EventIds.CreatedRecordOfSaleSapPayload.ToEventId(), "The record of sale SAP payload created. | _X-Correlation-ID : {_X-Correlation-ID}", correlationId); @@ -333,8 +325,8 @@ private SapRecordOfSalePayLoad BuildConvertLicencePayload(List _sapConfig; private readonly IRecordOfSaleSapMessageBuilder _recordOfSaleSapMessageBuilder; - private const string RecordOfSaleContainerName = "recordofsaleblobs"; - private const string SapXmlPayloadFileName = "SapXmlPayload.xml"; - private const string IncompleteStatus = "Incomplete"; - private const string JsonFileType = ".json"; - public AggregationService(ILogger logger, IAzureTableReaderWriter azureTableReaderWriter, IAzureBlobEventWriter azureBlobEventWriter, ISapClient sapClient, IOptions sapConfig, IRecordOfSaleSapMessageBuilder recordOfSaleSapMessageBuilder) @@ -50,11 +47,11 @@ public async Task MergeRecordOfSaleEvents(QueueMessage queueMessage) { _logger.LogInformation(EventIds.MessageDequeueCount.ToEventId(), "Dequeue Count : {DequeueCount} | _X-Correlation-ID : {_X-Correlation-ID} | EventID : {EventID}", queueMessage.DequeueCount.ToString(), message.CorrelationId, message.EventId); - string status = _azureTableReaderWriter.GetEntityStatus(message.CorrelationId); + var entity = await _azureTableReaderWriter.GetEntity(message.CorrelationId, Constants.RecordOfSaleEventTableName); - if (status == IncompleteStatus) + if (entity["Status"].ToString() == Status.Incomplete.ToString()) { - List blob = _azureBlobEventWriter.GetBlobNamesInFolder(RecordOfSaleContainerName, message.CorrelationId); + List blob = _azureBlobEventWriter.GetBlobNamesInFolder(Constants.RecordOfSaleEventContainerName, message.CorrelationId); if (message.RelatedEvents.All(x => blob.Contains(x))) { @@ -62,14 +59,14 @@ public async Task MergeRecordOfSaleEvents(QueueMessage queueMessage) { _logger.LogInformation(EventIds.DownloadRecordOfSaleEventFromAzureBlob.ToEventId(), "Webjob has started downloading record of sale events from blob. | _X-Correlation-ID : {_X-Correlation-ID} | EventID : {EventID}", message.CorrelationId, message.EventId); - string rosEvent = _azureBlobEventWriter.DownloadEvent(message.CorrelationId + '/' + eventId + JsonFileType, RecordOfSaleContainerName); + string rosEvent = _azureBlobEventWriter.DownloadEvent(message.CorrelationId + '/' + eventId + Constants.RecordOfSaleEventFileExtension, Constants.RecordOfSaleEventContainerName); rosEventList.Add(JsonConvert.DeserializeObject(rosEvent)!); } XmlDocument sapPayload = _recordOfSaleSapMessageBuilder.BuildRecordOfSaleSapMessageXml(rosEventList, message.CorrelationId); _logger.LogInformation(EventIds.UploadRecordOfSaleSapXmlPayloadInAzureBlob.ToEventId(), "Uploading the SAP xml payload for record of sale event in blob storage. | _X-Correlation-ID : {_X-Correlation-ID} | EventID : {EventID}", message.CorrelationId, message.EventId); - await _azureBlobEventWriter.UploadEvent(sapPayload.ToIndentedString(), RecordOfSaleContainerName, message.CorrelationId + '/' + SapXmlPayloadFileName); + await _azureBlobEventWriter.UploadEvent(sapPayload.ToIndentedString(), Constants.RecordOfSaleEventContainerName, message.CorrelationId + '/' + Constants.SapXmlPayloadFileName); _logger.LogInformation(EventIds.UploadedRecordOfSaleSapXmlPayloadInAzureBlob.ToEventId(), "SAP xml payload for record of sale event is uploaded in blob storage successfully. | _X-Correlation-ID : {_X-Correlation-ID} | EventID : {EventID}", message.CorrelationId, message.EventId); HttpResponseMessage response = await _sapClient.PostEventData(sapPayload, _sapConfig.Value.SapEndpointForRecordOfSale, _sapConfig.Value.SapServiceOperationForRecordOfSale, _sapConfig.Value.SapUsernameForRecordOfSale, _sapConfig.Value.SapPasswordForRecordOfSale); @@ -81,9 +78,8 @@ public async Task MergeRecordOfSaleEvents(QueueMessage queueMessage) _logger.LogInformation(EventIds.RecordOfSalePublishedEventDataPushedToSap.ToEventId(), "The record of sale event data has been sent to SAP successfully. | _X-Correlation-ID : {_X-Correlation-ID} | EventID : {EventID} | StatusCode: {StatusCode}", message.CorrelationId, message.EventId, response.StatusCode); - await _azureTableReaderWriter.UpdateRecordOfSaleEventStatus(message.CorrelationId); + await _azureTableReaderWriter.UpdateEntity(message.CorrelationId, Constants.RecordOfSaleEventTableName, new[] { new KeyValuePair("Status", Status.Complete.ToString()) }); } - else { _logger.LogWarning(EventIds.AllRelatedEventsAreNotPresentInBlob.ToEventId(), "All related events are not present in Azure blob. | _X-Correlation-ID : {_X-Correlation-ID} | EventID : {EventID}", message.CorrelationId, message.EventId); diff --git a/src/UKHO.ERPFacade.EventAggregation.WebJob/UKHO.ERPFacade.EventAggregation.WebJob.csproj b/src/UKHO.ERPFacade.EventAggregation.WebJob/UKHO.ERPFacade.EventAggregation.WebJob.csproj index 93225822..9f02240b 100644 --- a/src/UKHO.ERPFacade.EventAggregation.WebJob/UKHO.ERPFacade.EventAggregation.WebJob.csproj +++ b/src/UKHO.ERPFacade.EventAggregation.WebJob/UKHO.ERPFacade.EventAggregation.WebJob.csproj @@ -46,7 +46,7 @@ Always - + Always diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Configuration/TestConfig.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Configuration/TestConfig.cs index 92468a89..c7858b6d 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Configuration/TestConfig.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Configuration/TestConfig.cs @@ -8,7 +8,6 @@ public class TestConfig public ErpFacadeConfiguration ErpFacadeConfiguration { get; set; } public AzureADconfiguration AzureADConfiguration { get; set; } public AzureStorageConfiguration AzureStorageConfiguration { get; set; } - public string[] XmlActionList { get; set; } public string LicenceUpdatedPayloadTestData { get; set; } public string[] RosLicenceUpdateXmlList { get; set; } public string[] RoSLicenceUpdatedProdXmlList { get; set; } diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/RoSWebhookScenarios.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/RoSWebhookScenarios.cs index 35e99ffa..e0a05234 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/RoSWebhookScenarios.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/RoSWebhookScenarios.cs @@ -5,6 +5,7 @@ using UKHO.ERPFacade.API.FunctionalTests.Helpers; using UKHO.ERPFacade.API.FunctionalTests.Model; using UKHO.ERPFacade.API.FunctionalTests.Service; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.FunctionalTests.FunctionalTests { @@ -50,7 +51,7 @@ public async Task WhenValidRoSEventInRecordOfSalePublishedEventOptionsReceivedWi [TestCase("RoS01_ValidRoSMainHolding.json", TestName = "WhenValidRoSEventInRecordOfSalePublishedEventPostReceivedWithValidToken_ThenWebhookReturns200OkResponse")] public async Task WhenValidRoSEventInRecordOfSalePublishedEventPostReceivedWithValidToken_ThenWebhookReturns200OkResponse(string payloadFileName) { - string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", payloadFileName); + string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, payloadFileName); var response = await RosWebhookEndpoint.PostWebhookResponseAsync(filePath, await _authToken.GetAzureADToken(false)); response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK); } @@ -59,7 +60,7 @@ public async Task WhenValidRoSEventInRecordOfSalePublishedEventPostReceivedWithV [TestCase("RoS01_ValidRoSMainHolding.json", TestName = "WhenValidRoSEventInRecordOfSalePublishedEventPostReceivedWithInvalidToken_ThenWebhookReturns401UnauthorizedResponse")] public async Task WhenValidRoSEventInRecordOfSalePublishedEventPostReceivedWithInvalidToken_ThenWebhookReturns401UnauthorizedResponse(string payloadFileName) { - string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", payloadFileName); + string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, payloadFileName); var response = await RosWebhookEndpoint.PostWebhookResponseAsync(filePath, "invalidToken_abcd"); response.StatusCode.Should().Be(System.Net.HttpStatusCode.Unauthorized); } @@ -68,7 +69,7 @@ public async Task WhenValidRoSEventInRecordOfSalePublishedEventPostReceivedWithI [TestCase("RoS01_ValidRoSMainHolding.json", TestName = "WhenValidRoSEventInRecordOfSalePublishedEventPostReceivedWithInvalidToken_ThenWebhookReturns403ForbiddenResponse")] public async Task WhenValidRoSEventInRecordOfSalePublishedEventPostReceivedWithInvalidToken_ThenWebhookReturns403ForbiddenResponse(string payloadFileName) { - string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", payloadFileName); + string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, payloadFileName); var response = await RosWebhookEndpoint.PostWebhookResponseAsync(filePath, await _authToken.GetAzureADToken(true)); response.StatusCode.Should().Be(System.Net.HttpStatusCode.Forbidden); } @@ -80,7 +81,7 @@ public async Task WhenValidRoSEventInRecordOfSalePublishedEventPostReceivedWithI [TestCase("RoS11_InValidRoSwithNoCorrelationID.json", TestName = "WhenInValidRoSEventInRecordOfSalePublishedEventPostReceived_ThenWebhookReturns400BadRequestResponse")] public async Task WhenInValidRoSEventInRecordOfSalePublishedEventPostReceived_ThenWebhookReturns400BadRequestResponse(string payloadFileName) { - string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", payloadFileName); + string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, payloadFileName); var response = await RosWebhookEndpoint.PostWebhookResponseAsync("Bad Request", filePath, await _authToken.GetAzureADToken(false)); response.StatusCode.Should().Be(System.Net.HttpStatusCode.BadRequest); } @@ -89,7 +90,7 @@ public async Task WhenInValidRoSEventInRecordOfSalePublishedEventPostReceived_Th [TestCase("RoS12_UnSupportedPayloadType.xml", TestName = "WhenInvalidRoSEventInRecordOfSalePublishedEventPostReceivedWithInvalidPayloadType_ThenWebhookReturns415UnsupportedMediaResponse")] public async Task WhenInvalidRoSEventInRecordOfSalePublishedEventPostReceivedWithInvalidPayloadType_ThenWebhookReturns415UnsupportedMediaResponse(string payloadFileName) { - string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", payloadFileName); + string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, payloadFileName); var response = await RosWebhookEndpoint.PostWebhookResponseAsync("Unsupported Media Type", filePath, await _authToken.GetAzureADToken(false)); response.StatusCode.Should().Be(System.Net.HttpStatusCode.UnsupportedMediaType); } @@ -105,7 +106,7 @@ public async Task WhenInvalidRoSEventInRecordOfSalePublishedEventPostReceivedWit public async Task WhenValidRoSEventInRecordOfSalePublishedEventReceivedPostReceivedWithValidPayload_ThenWebhookReturns200OkResponse(string payloadJsonFileName) { Console.WriteLine("Scenario:" + payloadJsonFileName + "\n"); - string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", payloadJsonFileName); + string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, payloadJsonFileName); RestResponse response = await RosWebhookEndpoint.PostWebhookResponseAsync(filePath, await _authToken.GetAzureADToken(false)); response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK); } @@ -118,7 +119,7 @@ public async Task WhenValidRoSEventInRecordOfSalePublishedEventReceivedPostRecei public async Task WhenInvalidRoSEventInRecordOfSalePublishedEventPostReceivedWithInvalidPayload_ThenWebhookReturns500InternalServerError(string payloadJsonFileName) { Console.WriteLine("Scenario:" + payloadJsonFileName + "\n"); - string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", payloadJsonFileName); + string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, payloadJsonFileName); RestResponse response = await RosWebhookEndpoint.PostWebhookResponseAsync(filePath, await _authToken.GetAzureADToken(false)); response.StatusCode.Should().Be(System.Net.HttpStatusCode.InternalServerError); } @@ -129,18 +130,18 @@ public async Task WhenValidRoSEventsReceivedWithValidPayloadsForMerging_ThenWebh Console.WriteLine("Scenario: Merging ROS Events - " + firstEventPayloadJsonFileName + " & " + lastEventPayloadJsonFileName + "\n"); string generatedCorrelationId = SapXmlHelper.GenerateRandomCorrelationId(); - string generatedXmlFolder = Path.Combine(_projectDir, Config.TestConfig.GeneratedXmlFolder, "RoSPayloadTestData"); + string generatedXmlFolder = Path.Combine(_projectDir, Config.TestConfig.GeneratedXmlFolder, Constants.RosPayloadTestDataFolder); List listOfEventJsons = await JsonHelper.GetEventJsonListUsingFileNameAsync(new List { firstEventPayloadJsonFileName, lastEventPayloadJsonFileName }); //Send first event - string firstEventPayloadJsonFilePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", firstEventPayloadJsonFileName); + string firstEventPayloadJsonFilePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, firstEventPayloadJsonFileName); RestResponse firstEventResponse = await RosWebhookEndpoint.PostWebhookResponseAsyncForXml(generatedCorrelationId, firstEventPayloadJsonFilePath, true, false, generatedXmlFolder, null, await _authToken.GetAzureADToken(false)); //Assert if ROS webhook returns OK firstEventResponse.StatusCode.Should().Be(System.Net.HttpStatusCode.OK); //Send last event - Additionally we need to send list of all json files to compare total unitofsales items with final XML payload - string lastEventPayloadJsonFilePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", lastEventPayloadJsonFileName); + string lastEventPayloadJsonFilePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, lastEventPayloadJsonFileName); RestResponse lastEventResponse = await RosWebhookEndpoint.PostWebhookResponseAsyncForXml(generatedCorrelationId, lastEventPayloadJsonFilePath, false, true, generatedXmlFolder, listOfEventJsons, await _authToken.GetAzureADToken(false)); //Assert if ROS webhook returns OK @@ -155,9 +156,9 @@ public async Task WhenValidRoSMigrateLicencePublishedEventReceivedWithValidPaylo Console.WriteLine("Scenario: Merging ROS Events - " + firstEventPayloadJsonFileName + " & " + "\n"); string generatedCorrelationId = SapXmlHelper.GenerateRandomCorrelationId(); - string generatedXmlFolder = Path.Combine(_projectDir, Config.TestConfig.GeneratedXmlFolder, "RoSPayloadTestData"); + string generatedXmlFolder = Path.Combine(_projectDir, Config.TestConfig.GeneratedXmlFolder, Constants.RosPayloadTestDataFolder); List listOfEventJsons2 = await JsonHelper.GetEventJsonListUsingFileNameAsync(new List { firstEventPayloadJsonFileName }); - string firstEventPayloadJsonFilePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", firstEventPayloadJsonFileName); + string firstEventPayloadJsonFilePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, firstEventPayloadJsonFileName); RestResponse firstEventResponse = await RosWebhookEndpoint.PostWebhookResponseAsyncForXml(generatedCorrelationId, firstEventPayloadJsonFilePath, true, true, generatedXmlFolder, listOfEventJsons2, await _authToken.GetAzureADToken(false)); firstEventResponse.StatusCode.Should().Be(System.Net.HttpStatusCode.OK); } diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/WebhookScenarios.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/WebhookScenarios.cs index 3981d57a..ed6aaa79 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/WebhookScenarios.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/WebhookScenarios.cs @@ -10,7 +10,7 @@ namespace UKHO.ERPFacade.API.FunctionalTests.FunctionalTests [TestFixture] public class WebhookScenarios { - private WebhookEndpoint WebhookEndpoint { get; set; } + private S57WebhookEndpoint S57WebhookEndpoint { get; set; } private readonly ADAuthTokenProvider _authToken = new(); private readonly string _projectDir = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory)); @@ -20,13 +20,13 @@ public class WebhookScenarios [SetUp] public void Setup() { - WebhookEndpoint = new WebhookEndpoint(); + S57WebhookEndpoint = new S57WebhookEndpoint(); } [Test(Description = "WhenValidEventInNewEncContentPublishedEventOptions_ThenWebhookReturns200OkResponse"), Order(0)] public async Task WhenValidEventInNewEncContentPublishedEventOptions_ThenWebhookReturns200OkResponse() { - var response = await WebhookEndpoint.OptionWebhookResponseAsync(await _authToken.GetAzureADToken(false)); + var response = await S57WebhookEndpoint.OptionWebhookResponseAsync(await _authToken.GetAzureADToken(false)); response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK); } @@ -34,7 +34,7 @@ public async Task WhenValidEventInNewEncContentPublishedEventOptions_ThenWebhook public async Task WhenValidEventInNewEncContentPublishedEventReceivedWithValidToken_ThenWebhookReturns200OkResponse() { string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Config.TestConfig.WebhookPayloadFileName); - var response = await WebhookEndpoint.PostWebhookResponseAsync(filePath, await _authToken.GetAzureADToken(false)); + var response = await S57WebhookEndpoint.PostWebhookResponseAsync(filePath, await _authToken.GetAzureADToken(false)); response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK); } @@ -42,7 +42,7 @@ public async Task WhenValidEventInNewEncContentPublishedEventReceivedWithValidTo public async Task WhenValidEventInNewEncContentPublishedEventReceivedWithInvalidToken_ThenWebhookReturns401UnAuthorizedResponse() { string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Config.TestConfig.WebhookPayloadFileName); - var response = await WebhookEndpoint.PostWebhookResponseAsync(filePath, "invalidToken_abcd"); + var response = await S57WebhookEndpoint.PostWebhookResponseAsync(filePath, "invalidToken_abcd"); response.StatusCode.Should().Be(System.Net.HttpStatusCode.Unauthorized); } @@ -50,7 +50,7 @@ public async Task WhenValidEventInNewEncContentPublishedEventReceivedWithInvalid public async Task WhenValidEventInNewEncContentPublishedEventReceivedWithTokenHavingNoRole_ThenWebhookReturns403ForbiddenResponse() { string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, Config.TestConfig.WebhookPayloadFileName); - var response = await WebhookEndpoint.PostWebhookResponseAsync(filePath, await _authToken.GetAzureADToken(true)); + var response = await S57WebhookEndpoint.PostWebhookResponseAsync(filePath, await _authToken.GetAzureADToken(true)); response.StatusCode.Should().Be(System.Net.HttpStatusCode.Forbidden); } @@ -106,7 +106,7 @@ public async Task WhenValidEventInNewEncContentPublishedEventReceivedWithValidTo Console.WriteLine("Scenario:" + payloadJsonFileName + "\n"); string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, payloadJsonFileName); string generatedXmlFolder = Path.Combine(_projectDir, Config.TestConfig.GeneratedXmlFolder); - RestResponse response = await WebhookEndpoint.PostWebhookResponseAsyncForXml(filePath, generatedXmlFolder, await _authToken.GetAzureADToken(false), permitState ); + RestResponse response = await S57WebhookEndpoint.PostWebhookResponseAsyncForXml(filePath, generatedXmlFolder, await _authToken.GetAzureADToken(false), permitState ); response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK); } @@ -130,10 +130,10 @@ public async Task WhenValidEventInNewEncContentPublishedEventReceivedWithValidTo public async Task WhenMandatoryAttributeIsEmptyOrNullInPayload_ThenWebhookReturnsInternalServerErrorResponse(string attributeName, int index) { string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "MandatoryAttributeValidation.JSON"); - RestResponse response = await WebhookEndpoint.PostWebhookResponseForMandatoryAttributeValidation(filePath, await _authToken.GetAzureADToken(false), attributeName, index, "Remove"); + RestResponse response = await S57WebhookEndpoint.PostWebhookResponseForMandatoryAttributeValidation(filePath, await _authToken.GetAzureADToken(false), attributeName, index, "Remove"); response.StatusCode.Should().Be(System.Net.HttpStatusCode.InternalServerError); - response = await WebhookEndpoint.PostWebhookResponseForMandatoryAttributeValidation(filePath, await _authToken.GetAzureADToken(false), attributeName, index, "EmptyOrNull"); + response = await S57WebhookEndpoint.PostWebhookResponseForMandatoryAttributeValidation(filePath, await _authToken.GetAzureADToken(false), attributeName, index, "EmptyOrNull"); response.StatusCode.Should().Be(System.Net.HttpStatusCode.InternalServerError); } @@ -142,7 +142,7 @@ public async Task WhenPermitDecryptionFails_ThenWebhookReturnsInternalServerErro { string filePath = Path.Combine(_projectDir, Config.TestConfig.PayloadFolder, "NewCell.JSON"); const string permitString = "wwslkC9oG3rNcT4ZrgqX39pg9DuC9oSkBsl4kqiwr5h3nW6t0HUmlSaYhpdLEpO1"; //Invalid permit string to test permit decryption failure. - RestResponse response = await WebhookEndpoint.PostWebhookResponseAsyncForXml(filePath, "", await _authToken.GetAzureADToken(false), permitString); + RestResponse response = await S57WebhookEndpoint.PostWebhookResponseAsyncForXml(filePath, "", await _authToken.GetAzureADToken(false), permitString); response.StatusCode.Should().Be(System.Net.HttpStatusCode.InternalServerError); } } diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/AzureBlobStorageHelper.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/AzureBlobStorageHelper.cs index 384a6644..5e6c447d 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/AzureBlobStorageHelper.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/AzureBlobStorageHelper.cs @@ -1,29 +1,12 @@ using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using UKHO.ERPFacade.API.FunctionalTests.Configuration; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.FunctionalTests.Helpers { public class AzureBlobStorageHelper { - public string DownloadGeneratedXml(string expectedXmLfilePath, string blobContainer) - { - BlobServiceClient blobServiceClient = new(Config.TestConfig.AzureStorageConfiguration.ConnectionString); - BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(blobContainer); - BlobClient blobClient = containerClient.GetBlobClient("SapXmlPayload.xml"); - try - { - BlobDownloadInfo blobDownload = blobClient.Download(); - using FileStream downloadFileStream = new((expectedXmLfilePath + "\\" + blobContainer + ".xml"), FileMode.Create); - blobDownload.Content.CopyTo(downloadFileStream); - } - catch (Exception ex) - { - Console.WriteLine(blobContainer + " " + ex.Message); - } - return (expectedXmLfilePath + "\\" + blobContainer + ".xml"); - } - public bool VerifyBlobExists(string parentContainerName, string subContainerName) { BlobServiceClient blobServiceClient = new BlobServiceClient(Config.TestConfig.AzureStorageConfiguration.ConnectionString); @@ -43,15 +26,14 @@ public List GetBlobNamesInFolder(string blobContainerName, string corrId public string DownloadGeneratedXmlFile(string expectedXmlFilePath, string blobContainer, string parentContainerName) { string fileName = ""; - string licenceUpdatedXmlFile = "SapXmlPayload"; BlobServiceClient blobServiceClient = new BlobServiceClient(Config.TestConfig.AzureStorageConfiguration.ConnectionString); BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(parentContainerName + "\\" + blobContainer); - BlobClient blobClient = containerClient.GetBlobClient(blobContainer + "/" + licenceUpdatedXmlFile + ".xml"); + BlobClient blobClient = containerClient.GetBlobClient(blobContainer + "/" + Constants.SapXmlPayloadFileName); try { BlobDownloadInfo blobDownload = blobClient.Download(); - fileName = expectedXmlFilePath + "\\" + blobContainer + "\\" + licenceUpdatedXmlFile + ".xml"; + fileName = expectedXmlFilePath + "\\" + blobContainer + "\\" + Constants.SapXmlPayloadFileName; Directory.CreateDirectory(Path.GetDirectoryName(fileName)); using FileStream downloadFileStream = new(fileName, FileMode.Create); blobDownload.Content.CopyTo(downloadFileStream); diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/AzureTableHelper.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/AzureTableHelper.cs index 8ad53b73..aa8b2073 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/AzureTableHelper.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/AzureTableHelper.cs @@ -3,14 +3,12 @@ using Azure; using UKHO.ERPFacade.Common.Models.TableEntities; using UKHO.ERPFacade.API.FunctionalTests.Configuration; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.FunctionalTests.Helpers { public class AzureTableHelper { - private const string ErpFacadeTableName = "encevents"; - private const string RoSEventsTableName = "recordofsaleevents"; - //Private Methods private static TableClient GetTableClient(string tableName) { @@ -27,10 +25,10 @@ private static TableClient GetTableClient(string tableName) return tableClient; } - + public static string GetSapStatus(string correlationId) { - TableClient tableClient = GetTableClient(RoSEventsTableName); + TableClient tableClient = GetTableClient(Constants.RecordOfSaleEventTableName); Pageable existingEntity = tableClient.Query(filter: TableClient.CreateQueryFilter($"CorrelationId eq {correlationId}")); return existingEntity != null ? existingEntity.FirstOrDefault()?.Status : string.Empty; } diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/JSONHelper.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/JSONHelper.cs index 4c3bb759..053b3a1c 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/JSONHelper.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/JSONHelper.cs @@ -2,6 +2,7 @@ using Newtonsoft.Json.Linq; using UKHO.ERPFacade.API.FunctionalTests.Configuration; using UKHO.ERPFacade.API.FunctionalTests.Model; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.FunctionalTests.Helpers { @@ -15,7 +16,7 @@ public static async Task> GetEventJsonListUsingFi { List listOfEventJson = new(); - foreach (var filePath in fileNames.Select(fileName => Path.Combine(projectDir, Config.TestConfig.PayloadFolder, "RoSPayloadTestData", fileName))) + foreach (var filePath in fileNames.Select(fileName => Path.Combine(projectDir, Config.TestConfig.PayloadFolder, Constants.RosPayloadTestDataFolder, fileName))) { string requestBody; @@ -31,17 +32,17 @@ public static async Task> GetEventJsonListUsingFi public static string ModifyMandatoryAttribute(string payload, string attributeName, int index, string action) { - payload = SapXmlHelper.UpdatePermitField(payload, "PermitWithSameKey"); + payload = SapXmlHelper.UpdatePermitField(payload, Constants.PermitWithSameKey); JObject jsonObject = JObject.Parse(payload); string[] types = attributeName.Split("."); - var tokens = types[0] == "products" - ? jsonObject.SelectTokens($"$.data.products[{index}].{types[1]}").ToList() - : types[0] == "unitsOfSale" - ? jsonObject.SelectTokens($"$.data.unitsOfSale[{index}].{types[1]}").ToList() - : jsonObject.SelectTokens($"$.data.ukhoWeekNumber.{types[0]}").ToList(); + var tokens = types[0] == Constants.Products + ? jsonObject.SelectTokens($"$.{Constants.ProductsNode}[{index}].{types[1]}").ToList() + : types[0] == Constants.UnitsOfSale + ? jsonObject.SelectTokens($"$.{Constants.UnitsOfSaleNode}[{index}].{types[1]}").ToList() + : jsonObject.SelectTokens($"$.{Constants.UKHOWeekNumber}.{types[0]}").ToList(); if (action == "Remove") { diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/LicenceUpdateXMLHelper.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/LicenceUpdateXMLHelper.cs index 2bf7ff0d..65fef68f 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/LicenceUpdateXMLHelper.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/LicenceUpdateXMLHelper.cs @@ -5,6 +5,7 @@ using System.Xml; using UKHO.ERPFacade.API.FunctionalTests.Model; using UKHO.ERPFacade.API.FunctionalTests.Configuration; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.FunctionalTests.Helpers { @@ -22,7 +23,7 @@ public static async Task CheckXmlAttributes(JsonInputLicenceUpdateHelper j XmlDocument xmlDoc = new(); xmlDoc.LoadXml(await File.ReadAllTextAsync(xmlFilePath)); - while (xmlDoc.DocumentElement.Name == "soap:Envelope" || xmlDoc.DocumentElement.Name == "soap:Body") + while (xmlDoc.DocumentElement.Name == Constants.SoapEnvelope || xmlDoc.DocumentElement.Name == Constants.SoapBody) { string tempXmlString = xmlDoc.DocumentElement.InnerXml; xmlDoc.LoadXml(tempXmlString); @@ -41,7 +42,7 @@ public static async Task CheckXmlAttributes(JsonInputLicenceUpdateHelper j if (licResult.SERVICETYPE.Equals(licenceJsonFields.productType)) { - if (licResult.LICTRANSACTION.Equals("CHANGELICENCE")) + if (licResult.LICTRANSACTION.Equals(Constants.LicTransaction)) { Assert.That(VerifyChangeLicense(licResult, licenceJsonFields), Is.True); } @@ -75,8 +76,8 @@ public static async Task CheckXmlAttributes(JsonInputLicenceUpdateHelper j if (!licResult.USERS.Equals(licenceFieldsJson.numberLicenceUsers)) s_attrNotMatched.Add(nameof(licResult.USERS)); - string[] fieldNames = { "STARTDATE", "ENDDATE", "SHOREBASED", "LTYPE", "LICDUR", "PO", "ADSORDNO" }; - string[] fieldNamesProduct = { "ID", "ENDDA", "DURATION", "RENEW", "REPEAT" }; + string[] fieldNames = { Constants.StartDate, Constants.EndDate, Constants.ShoreBased, Constants.LType, Constants.LicDur, Constants.ProductOrder, Constants.AdsOrderNumber }; + string[] fieldNamesProduct = { Constants.Id, Constants.ProductEndDate, Constants.Duration, Constants.Renew, Constants.Repeat }; Z_ADDS_ROSIM_ORDERItem[] items = licResult.PROD; VerifyBlankFields(licResult, fieldNames); VerifyBlankProductFields(items[0], fieldNamesProduct); diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/RoSXMLHelper.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/RoSXMLHelper.cs index 131bed1a..3cc09764 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/RoSXMLHelper.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/RoSXMLHelper.cs @@ -5,6 +5,7 @@ using System.Xml; using UKHO.ERPFacade.API.FunctionalTests.Model; using UKHO.ERPFacade.API.FunctionalTests.Configuration; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.FunctionalTests.Helpers { @@ -21,7 +22,7 @@ public static async Task CheckXmlAttributes(string generatedXmlFilePath, s //Read XML payload generated by webjob XmlDocument xmlDoc = new(); xmlDoc.LoadXml(await File.ReadAllTextAsync(generatedXmlFilePath)); - while (xmlDoc.DocumentElement is { Name: "soap:Envelope" or "soap:Body" }) + while (xmlDoc.DocumentElement is { Name: Constants.SoapEnvelope or Constants.SoapBody }) { string xmlString = xmlDoc.DocumentElement.InnerXml; xmlDoc.LoadXml(xmlString); @@ -52,19 +53,19 @@ public static async Task CheckXmlAttributes(string generatedXmlFilePath, s { switch (rosXmlPayload.LICTRANSACTION) { - case "MAINTAINHOLDINGS": + case Constants.MaintainHoldingsType: Assert.That(VerifyMaintainHolding(rosXmlPayload, roSJsonFields, listOfEventJson), Is.True); break; - case "NEWLICENCE": + case Constants.NewLicenceType: Assert.That(VerifyNewLicence(rosXmlPayload, roSJsonFields, listOfEventJson), Is.True); break; - case "MIGRATENEWLICENCE": + case Constants.MigrateNewLicenceType: Assert.That(VerifyMigrateNewLicence(rosXmlPayload, roSJsonFields, listOfEventJson), Is.True); break; - case "MIGRATEEXISTINGLICENCE": + case Constants.MigrateExistingLicenceType: Assert.That(VerifyMigrateExistingLicence(rosXmlPayload, roSJsonFields, listOfEventJson), Is.True); break; - case "CONVERTLICENCE": + case Constants.ConvertLicenceType: Assert.That(VerifyConvertTrialToFullLicence(rosXmlPayload, roSJsonFields, listOfEventJson), Is.True); break; } @@ -85,7 +86,7 @@ public static async Task CheckXmlAttributes(string generatedXmlFilePath, s if (!rosXmlPayload.ADSORDNO.Equals(roSJsonPayload.ordernumber)) s_attrNotMatched.Add(nameof(rosXmlPayload.ADSORDNO)); - string[] fieldNames = { "SOLDTOACC", "LICENSEEACC", "STARTDATE", "ENDDATE", "VNAME", "IMO", "CALLSIGN", "SHOREBASED", "FLEET", "USERS", "ENDUSERID", "ECDISMANUF", "LTYPE", "LICDUR" }; + string[] fieldNames = { Constants.SoldToAcc, Constants.LicenceAcc, Constants.StartDate, Constants.EndDate, Constants.VName, Constants.Imo, Constants.CallSign, Constants.ShoreBased, Constants.Fleet, Constants.Users, Constants.EndUserId, Constants.EcdisManUf, Constants.LType, Constants.LicDur }; Z_ADDS_ROSIM_ORDERItem[] xmlUnitOfSaleItems = rosXmlPayload.PROD; List jsonUnitOfSalesItems = listOfEventJsons.SelectMany(eventJson => eventJson.data.recordsOfSale.unitsOfSale).ToList(); @@ -136,8 +137,8 @@ public static async Task CheckXmlAttributes(string generatedXmlFilePath, s if (!rosXmlPayload.LICDUR.Equals(roSJsonPayload.licenceDuration)) s_attrNotMatched.Add(nameof(rosXmlPayload.LICDUR)); - List blankFieldNames = new() { "LICNO", "FLEET" }; - List blankProductFieldNames = new() { "REPEAT" }; + List blankFieldNames = new() { Constants.LicNo, Constants.Fleet }; + List blankProductFieldNames = new() { Constants.Repeat }; Z_ADDS_ROSIM_ORDERItem[] xmlUnitOfSaleItems = rosXmlPayload.PROD; List jsonUnitOfSalesItems = listOfEventJsons.SelectMany(eventJson => eventJson.data.recordsOfSale.unitsOfSale).ToList(); @@ -188,8 +189,8 @@ public static async Task CheckXmlAttributes(string generatedXmlFilePath, s if (!rosXmlPayload.LICDUR.Equals(roSJsonPayload.licenceDuration)) s_attrNotMatched.Add(nameof(rosXmlPayload.LICDUR)); - List blankFieldNames = new() { "LICNO", "FLEET" }; - List blankProductFieldNames = new() { "REPEAT" }; + List blankFieldNames = new() { Constants.LicNo, Constants.Fleet }; + List blankProductFieldNames = new() { Constants.Repeat }; Z_ADDS_ROSIM_ORDERItem[] xmlUnitOfSaleItems = rosXmlPayload.PROD; List jsonUnitOfSalesItems = listOfEventJsons.SelectMany(eventJson => eventJson.data.recordsOfSale.unitsOfSale).ToList(); @@ -221,7 +222,7 @@ public static async Task CheckXmlAttributes(string generatedXmlFilePath, s if (!rosXmlPayload.ADSORDNO.Equals(roSJsonPayload.ordernumber)) s_attrNotMatched.Add(nameof(rosXmlPayload.ADSORDNO)); - string[] fieldNames = { "SOLDTOACC", "LICENSEEACC", "STARTDATE", "ENDDATE", "VNAME", "IMO", "CALLSIGN", "SHOREBASED", "FLEET", "USERS", "ENDUSERID", "ECDISMANUF", "LTYPE", "LICDUR" }; + string[] fieldNames = { Constants.SoldToAcc, Constants.LicenceAcc, Constants.StartDate, Constants.EndDate, Constants.VName, Constants.Imo, Constants.CallSign, Constants.ShoreBased, Constants.Fleet, Constants.Users, Constants.EndUserId, Constants.EcdisManUf, Constants.LType, Constants.LicDur }; Z_ADDS_ROSIM_ORDERItem[] xmlUnitOfSaleItems = rosXmlPayload.PROD; List jsonUnitOfSalesItems = listOfEventJsons.SelectMany(eventJson => eventJson.data.recordsOfSale.unitsOfSale).ToList(); @@ -255,7 +256,7 @@ public static async Task CheckXmlAttributes(string generatedXmlFilePath, s if (!rosXmlPayload.ADSORDNO.Equals(roSJsonPayload.ordernumber)) s_attrNotMatched.Add(nameof(rosXmlPayload.ADSORDNO)); - string[] fieldNames = { "SOLDTOACC", "LICENSEEACC", "STARTDATE", "ENDDATE", "VNAME", "IMO", "CALLSIGN", "SHOREBASED", "FLEET", "USERS", "ENDUSERID", "ECDISMANUF"}; + string[] fieldNames = { Constants.SoldToAcc, Constants.LicenceAcc, Constants.StartDate, Constants.EndDate, Constants.VName, Constants.Imo, Constants.CallSign, Constants.ShoreBased, Constants.Fleet, Constants.Users, Constants.EndUserId, Constants.EcdisManUf }; Z_ADDS_ROSIM_ORDERItem[] xmlUnitOfSaleItems = rosXmlPayload.PROD; List jsonUnitOfSalesItems = listOfEventJsons.SelectMany(eventJson => eventJson.data.recordsOfSale.unitsOfSale).ToList(); diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/SAPXmlHelper.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/SAPXmlHelper.cs index 5fb78f38..03d13cea 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/SAPXmlHelper.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Helpers/SAPXmlHelper.cs @@ -2,6 +2,8 @@ using System.Xml.Linq; using Newtonsoft.Json.Linq; using UKHO.ERPFacade.API.FunctionalTests.Configuration; +using UKHO.ERPFacade.Common.Constants; + namespace UKHO.ERPFacade.API.FunctionalTests.Helpers { public class SapXmlHelper @@ -18,32 +20,32 @@ public static string GenerateRandomCorrelationId() randomCorrId = randomCorrId.Insert(5, "-"); randomCorrId = randomCorrId.Insert(11, "-"); randomCorrId = randomCorrId.Insert(16, "-"); - var currentTimeStamp = DateTime.Now.ToString("yyyyMMdd"); + var currentTimeStamp = DateTime.Now.ToString(Constants.RecDateFormat); randomCorrId = "ft-" + currentTimeStamp + "-" + randomCorrId; return randomCorrId; } public static string UpdateTimeAndCorrIdField(string requestBody, string generatedCorrelationId) { - var currentTimeStamp = DateTime.Now.ToString("yyyy-MM-dd"); + var currentTimeStamp = DateTime.Now.ToString(Constants.RecDateFormat); JObject jsonObj = JObject.Parse(requestBody); jsonObj["time"] = currentTimeStamp; - jsonObj["data"]["correlationId"] = generatedCorrelationId; + jsonObj[Constants.DataNode]["correlationId"] = generatedCorrelationId; return jsonObj.ToString(); } public static string UpdatePermitField(string requestBody, string permitState) { JObject jsonObj = JObject.Parse(requestBody); - var products = jsonObj["data"]["products"]; + var products = jsonObj[Constants.DataNode][Constants.Products]; - string permit = permitState.Contains("Same") ? Config.TestConfig.PermitWithSameKey.Permit - : permitState.Contains("Different") ? Config.TestConfig.PermitWithDifferentKey.Permit + string permit = permitState.Contains(Constants.PermitWithSameKey) ? Config.TestConfig.PermitWithSameKey.Permit + : permitState.Contains(Constants.PermitWithDifferentKey) ? Config.TestConfig.PermitWithDifferentKey.Permit : permitState; foreach (var product in products) { - product["permit"] = permit; + product[Constants.Permit] = permit; } return jsonObj.ToString(); @@ -68,8 +70,8 @@ public static bool VerifyGeneratedXml(string generatedXmlFilePath, string xmlFil var expectedAttributes = expectedXml.Descendants("item").ToList(); - string activeKey = permitState == "PermitWithSameKey" ? permitWithSameKeyActiveKey : permitWithDifferentKeyActiveKey; - string nextKey = permitState == "PermitWithSameKey" ? permitWithSameKeyNextKey : permitWithDifferentKeyNextKey; + string activeKey = permitState == Constants.PermitWithSameKey ? permitWithSameKeyActiveKey : permitWithDifferentKeyActiveKey; + string nextKey = permitState == Constants.PermitWithSameKey ? permitWithSameKeyNextKey : permitWithDifferentKeyNextKey; // Ensure both XMLs have the same number of items if (generatedAttributes.Count != expectedAttributes.Count) @@ -89,7 +91,7 @@ public static bool VerifyGeneratedXml(string generatedXmlFilePath, string xmlFil { var expectedAttribute = expectedAction.Element(generatedAttribute.Name); - if ((action == "CREATE ENC CELL" || action == "UPDATE ENC CELL EDITION UPDATE NUMBER") && (generatedAttribute.Name == "ACTIVEKEY" || generatedAttribute.Name == "NEXTKEY")) + if ((action == Constants.CreateEncCell || action == Constants.UpdateCell ) && (generatedAttribute.Name == Constants.ActiveKey || generatedAttribute.Name == Constants.NextKey)) { string expectedValue = generatedAttribute.Name == "ACTIVEKEY" ? activeKey : nextKey; diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Service/LicenceUpdatedEndpoint.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Service/LicenceUpdatedEndpoint.cs index fc2936a7..deba40d2 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Service/LicenceUpdatedEndpoint.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Service/LicenceUpdatedEndpoint.cs @@ -5,6 +5,7 @@ using UKHO.ERPFacade.API.FunctionalTests.Configuration; using UKHO.ERPFacade.API.FunctionalTests.Helpers; using UKHO.ERPFacade.API.FunctionalTests.Model; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.FunctionalTests.Service { @@ -13,8 +14,6 @@ public class LicenceUpdatedEndpoint private readonly RestClient _client; private readonly AzureBlobStorageHelper _azureBlobStorageHelper; - private const string LicenceUpdatedRequestEndPoint = "/webhook/licenceupdatedpublishedeventreceived"; - public static string GeneratedCorrelationId = string.Empty; public LicenceUpdatedEndpoint() @@ -26,7 +25,7 @@ public LicenceUpdatedEndpoint() public async Task OptionLicenceUpdatedWebhookResponseAsync(string token) { - var request = new RestRequest(LicenceUpdatedRequestEndPoint, Method.Options); + var request = new RestRequest(Constants.LicenceUpdatedRequestEndPoint, Method.Options); request.AddHeader("Authorization", "Bearer " + token); RestResponse response = await _client.ExecuteAsync(request); return response; @@ -44,7 +43,7 @@ public async Task PostLicenceUpdatedWebhookResponseAsync(string pa GeneratedCorrelationId = SapXmlHelper.GenerateRandomCorrelationId(); requestBody = SapXmlHelper.UpdateTimeAndCorrIdField(requestBody, GeneratedCorrelationId); - var request = new RestRequest(LicenceUpdatedRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.LicenceUpdatedRequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/json"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/json", requestBody, ParameterType.RequestBody); @@ -70,7 +69,7 @@ public async Task PostLicenceUpdatedWebhookResponseAsync(string sc if (scenarioName == "Bad Request") { - var request = new RestRequest(LicenceUpdatedRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.LicenceUpdatedRequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/json"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/json", requestBody, ParameterType.RequestBody); @@ -80,7 +79,7 @@ public async Task PostLicenceUpdatedWebhookResponseAsync(string sc } else if (scenarioName == "Unsupported Media Type") { - var request = new RestRequest(LicenceUpdatedRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.LicenceUpdatedRequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/xml"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/xml", requestBody, ParameterType.RequestBody); @@ -104,13 +103,13 @@ public async Task PostLicenceUpdatedResponseAsyncForXML(string fil } GeneratedCorrelationId = SapXmlHelper.GenerateRandomCorrelationId(); requestBody = SapXmlHelper.UpdateTimeAndCorrIdField(requestBody, GeneratedCorrelationId); - var request = new RestRequest(LicenceUpdatedRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.LicenceUpdatedRequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/json"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/json", requestBody, ParameterType.RequestBody); RestResponse response = await _client.ExecuteAsync(request); JsonInputLicenceUpdateHelper jsonPayload = JsonConvert.DeserializeObject(requestBody); - string generatedXmlFilePath = _azureBlobStorageHelper.DownloadGeneratedXmlFile(generatedXmlFolder, GeneratedCorrelationId, "licenceupdatedblobs"); + string generatedXmlFilePath = _azureBlobStorageHelper.DownloadGeneratedXmlFile(generatedXmlFolder, GeneratedCorrelationId, Constants.LicenceUpdatedEventContainerName); if (response.StatusCode == System.Net.HttpStatusCode.OK) { Assert.That(LicenceUpdateXmlHelper.CheckXmlAttributes(jsonPayload, generatedXmlFilePath, requestBody).Result, Is.True, "CheckXmlAttributes Failed"); diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Service/RoSWebhookEndpoint.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Service/RoSWebhookEndpoint.cs index c9be8d88..2a6ac801 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Service/RoSWebhookEndpoint.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Service/RoSWebhookEndpoint.cs @@ -4,7 +4,7 @@ using UKHO.ERPFacade.API.FunctionalTests.Configuration; using UKHO.ERPFacade.API.FunctionalTests.Helpers; using UKHO.ERPFacade.API.FunctionalTests.Model; -using Newtonsoft.Json; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.FunctionalTests.Service { @@ -12,9 +12,8 @@ public class RoSWebhookEndpoint { private readonly RestClient _client; private readonly AzureBlobStorageHelper _azureBlobStorageHelper; - private const string RoSWebhookRequestEndPoint = "/webhook/recordofsalepublishedeventreceived"; + public static string GeneratedCorrelationId = string.Empty; - public const string RecordOfSalesContainerName = "recordofsaleblobs"; public RoSWebhookEndpoint() { @@ -26,7 +25,7 @@ public RoSWebhookEndpoint() public async Task OptionRosWebhookResponseAsync(string token) { - var request = new RestRequest(RoSWebhookRequestEndPoint, Method.Options); + var request = new RestRequest(Constants.RoSWebhookRequestEndPoint, Method.Options); request.AddHeader("Authorization", "Bearer " + token); RestResponse response = await _client.ExecuteAsync(request); return response; @@ -44,7 +43,7 @@ public async Task PostWebhookResponseAsync(string payloadFilePath, GeneratedCorrelationId = SapXmlHelper.GenerateRandomCorrelationId(); requestBody = SapXmlHelper.UpdateTimeAndCorrIdField(requestBody, GeneratedCorrelationId); - var request = new RestRequest(RoSWebhookRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.RoSWebhookRequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/json"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/json", requestBody, ParameterType.RequestBody); @@ -52,7 +51,7 @@ public async Task PostWebhookResponseAsync(string payloadFilePath, if (response.StatusCode == HttpStatusCode.OK) { - bool isBlobCreated = _azureBlobStorageHelper.VerifyBlobExists(RecordOfSalesContainerName, GeneratedCorrelationId); + bool isBlobCreated = _azureBlobStorageHelper.VerifyBlobExists(Constants.RecordOfSaleEventContainerName, GeneratedCorrelationId); Assert.That(isBlobCreated, Is.True, $"Blob {GeneratedCorrelationId} not created"); } @@ -71,7 +70,7 @@ public async Task PostWebhookResponseAsyncForXml(string correlatio requestBody = SapXmlHelper.UpdateTimeAndCorrIdField(requestBody, correlationId); - var request = new RestRequest(RoSWebhookRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.RoSWebhookRequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/json"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/json", requestBody, ParameterType.RequestBody); @@ -84,29 +83,29 @@ public async Task PostWebhookResponseAsyncForXml(string correlatio if (isFirstEvent) { - bool isBlobCreated = _azureBlobStorageHelper.VerifyBlobExists(RecordOfSalesContainerName, correlationId); + bool isBlobCreated = _azureBlobStorageHelper.VerifyBlobExists(Constants.RecordOfSaleEventContainerName, correlationId); Assert.That(isBlobCreated, Is.True, $"Blob for {correlationId} not created"); } - blobList = _azureBlobStorageHelper.GetBlobNamesInFolder(RecordOfSalesContainerName, correlationId); + blobList = _azureBlobStorageHelper.GetBlobNamesInFolder(Constants.RecordOfSaleEventContainerName, correlationId); switch (isLastEvent) { case true: DateTime startTime = DateTime.UtcNow; //10minutes polling after every 30 seconds to check if xml payload is generated during webjob execution. - while (!blobList.Contains("SapXmlPayload") && DateTime.UtcNow - startTime < TimeSpan.FromMinutes(10)) + while (!blobList.Contains(Constants.SapXmlPayloadFileName) && DateTime.UtcNow - startTime < TimeSpan.FromMinutes(10)) { - blobList = _azureBlobStorageHelper.GetBlobNamesInFolder(RecordOfSalesContainerName, correlationId); + blobList = _azureBlobStorageHelper.GetBlobNamesInFolder(Constants.RecordOfSaleEventContainerName, correlationId); await Task.Delay(30000); } - Assert.That(blobList, Does.Contain("SapXmlPayload"), $"XML is not generated for {correlationId} at {DateTime.Now}."); + Assert.That(blobList, Does.Contain(Constants.SapXmlPayloadFileName), $"XML is not generated for {correlationId} at {DateTime.Now}."); string generatedXmlFilePath = _azureBlobStorageHelper.DownloadGeneratedXmlFile(generatedXmlFolder, correlationId, "recordofsaleblobs"); Assert.That(RoSXmlHelper.CheckXmlAttributes(generatedXmlFilePath, requestBody, listOfEventJsons).Result, Is.True, "CheckXmlAttributes Failed"); Assert.That(AzureTableHelper.GetSapStatus(correlationId), Is.EqualTo("Complete"), $"SAP status is Incomplete for {correlationId}"); break; case false: - Assert.That(blobList, Does.Not.Contain("SapXmlPayload"), $"XML is generated for {correlationId} before we receive all related events."); + Assert.That(blobList, Does.Not.Contain(Constants.SapXmlPayloadFileName), $"XML is generated for {correlationId} before we receive all related events."); Assert.That(AzureTableHelper.GetSapStatus(correlationId), Is.EqualTo("Incomplete"), $"SAP status is Complete for {correlationId}"); break; } @@ -126,7 +125,7 @@ public async Task PostWebhookResponseAsync(string scenarioName, st { case "Bad Request": { - var request = new RestRequest(RoSWebhookRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.RoSWebhookRequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/json"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/json", requestBody, ParameterType.RequestBody); @@ -135,7 +134,7 @@ public async Task PostWebhookResponseAsync(string scenarioName, st } case "Unsupported Media Type": { - var request = new RestRequest(RoSWebhookRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.RoSWebhookRequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/xml"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/xml", requestBody, ParameterType.RequestBody); diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Service/WebhookEndpoint.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Service/S57WebhookEndpoint.cs similarity index 86% rename from tests/UKHO.ERPFacade.API.FunctionalTests/Service/WebhookEndpoint.cs rename to tests/UKHO.ERPFacade.API.FunctionalTests/Service/S57WebhookEndpoint.cs index e3ae5cdd..fbc14e5d 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Service/WebhookEndpoint.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Service/S57WebhookEndpoint.cs @@ -4,20 +4,19 @@ using UKHO.ERPFacade.API.FunctionalTests.Configuration; using UKHO.ERPFacade.API.FunctionalTests.Helpers; using UKHO.ERPFacade.API.FunctionalTests.Model; +using UKHO.ERPFacade.Common.Constants; namespace UKHO.ERPFacade.API.FunctionalTests.Service { - public class WebhookEndpoint + public class S57WebhookEndpoint { private readonly RestClient _client; private readonly AzureBlobStorageHelper _azureBlobStorageHelper; private readonly RestClientOptions _options; - private const string WebhookRequestEndPoint = "/webhook/newenccontentpublishedeventreceived"; - public static string GeneratedCorrelationId = string.Empty; - public WebhookEndpoint() + public S57WebhookEndpoint() { _azureBlobStorageHelper = new AzureBlobStorageHelper(); _options = new RestClientOptions(Config.TestConfig.ErpFacadeConfiguration.BaseUrl); @@ -26,7 +25,7 @@ public WebhookEndpoint() public async Task OptionWebhookResponseAsync(string token) { - var request = new RestRequest(WebhookRequestEndPoint); + var request = new RestRequest(Constants.S57RequestEndPoint); request.AddHeader("Authorization", "Bearer " + token); var response = await _client.OptionsAsync(request); return response; @@ -42,7 +41,7 @@ public async Task PostWebhookResponseAsync(string filePath, string } GeneratedCorrelationId = SapXmlHelper.GenerateRandomCorrelationId(); requestBody = SapXmlHelper.UpdateTimeAndCorrIdField(requestBody, GeneratedCorrelationId); - var request = new RestRequest(WebhookRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.S57RequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/json"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/json", requestBody, ParameterType.RequestBody); @@ -61,7 +60,7 @@ public async Task PostWebhookResponseAsyncForXml(string filePath, } requestBody = SapXmlHelper.UpdatePermitField(requestBody, permitState); - var request = new RestRequest(WebhookRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.S57RequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/json"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/json", requestBody, ParameterType.RequestBody); @@ -74,10 +73,10 @@ public async Task PostWebhookResponseAsyncForXml(string filePath, if (response.StatusCode == System.Net.HttpStatusCode.OK) { //Logic to download XML from container using TraceID from JSON - string generatedXmlFilePath = _azureBlobStorageHelper.DownloadGeneratedXml(generatedXmlFolder, correlationId); + string generatedXmlFilePath = _azureBlobStorageHelper.DownloadGeneratedXmlFile(generatedXmlFolder, correlationId, Constants.S57EventContainerName); //Expected XML - string xmlFilePath = filePath.Replace(Config.TestConfig.PayloadFolder, "ERPFacadeExpectedXmlFiles").Replace(".JSON", ".xml"); + string xmlFilePath = filePath.Replace(Config.TestConfig.PayloadFolder, Constants.ErpFacadeExpectedXmlFiles).Replace(".JSON", ".xml"); Assert.That(SapXmlHelper.VerifyGeneratedXml(generatedXmlFilePath, xmlFilePath, permitState)); } @@ -94,7 +93,7 @@ public async Task PostWebhookResponseForMandatoryAttributeValidati } requestBody = JsonHelper.ModifyMandatoryAttribute(requestBody, attributeName, index, action); - var request = new RestRequest(WebhookRequestEndPoint, Method.Post); + var request = new RestRequest(Constants.S57RequestEndPoint, Method.Post); request.AddHeader("Content-Type", "application/json"); request.AddHeader("Authorization", "Bearer " + token); request.AddParameter("application/json", requestBody, ParameterType.RequestBody); diff --git a/tests/UKHO.ERPFacade.API.UnitTests/Controllers/WebhookControllerTests.cs b/tests/UKHO.ERPFacade.API.UnitTests/Controllers/WebhookControllerTests.cs index 63af4249..b87af107 100644 --- a/tests/UKHO.ERPFacade.API.UnitTests/Controllers/WebhookControllerTests.cs +++ b/tests/UKHO.ERPFacade.API.UnitTests/Controllers/WebhookControllerTests.cs @@ -5,6 +5,7 @@ using System.Net.Http; using System.Threading.Tasks; using System.Xml; +using Azure.Data.Tables; using FakeItEasy; using FluentAssertions; using Microsoft.AspNetCore.Http; @@ -114,10 +115,10 @@ public async Task WhenValidEventInNewEncContentPublishedEventReceived_ThenWebhoo var result = (OkObjectResult)await _fakeWebHookController.NewEncContentPublishedEventReceived(fakeEncEventJson); - A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored)).MustHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateRequestTimeEntity(A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpdateEntity(A.Ignored, A.Ignored, A[]>.Ignored)).MustHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(2, Times.Exactly); - A.CallTo(() => _fakeSapClient.PostEventData(A.Ignored, A.Ignored, "Z_ADDS_MAT_INFO", A.Ignored, A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeSapClient.PostEventData(A.Ignored, A.Ignored, A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); result.StatusCode.Should().Be(200); @@ -166,8 +167,8 @@ public async Task WhenCorrelationIdIsMissingInNewEncContentPublishedEvent_ThenWe result.StatusCode.Should().Be(400); - A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored)).MustNotHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateRequestTimeEntity(A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpdateEntity(A.Ignored, A.Ignored, A[]>.Ignored)).MustNotHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" @@ -197,8 +198,8 @@ public void WhenSapDoesNotRespond200Ok_ThenWebhookReturns500InternalServerRespon Assert.ThrowsAsync(() => _fakeWebHookController.NewEncContentPublishedEventReceived(fakeEncEventJson)); - A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored)).MustHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateRequestTimeEntity(A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpdateEntity(A.Ignored, A.Ignored, A[]>.Ignored)).MustNotHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" @@ -287,7 +288,7 @@ public async Task WhenValidEventInRecordOfSalePublishedEventReceived_ThenWebhook var result = (OkObjectResult)await _fakeWebHookController.RecordOfSalePublishedEventReceived(fakeRosEventJson); result.StatusCode.Should().Be(200); - A.CallTo(() => _fakeAzureTableReaderWriter.UpsertRecordOfSaleEntity(A.Ignored)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappenedOnceExactly(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappenedOnceExactly(); A.CallTo(() => _fakeAzureQueueHelper.AddMessage(fakeRosEventJson)).MustHaveHappenedOnceExactly(); @@ -331,7 +332,7 @@ public async Task WhenCorrelationIdIsMissingInRecordOfSalePublishedEvent_ThenWeb result.StatusCode.Should().Be(400); - A.CallTo(() => _fakeAzureTableReaderWriter.UpsertRecordOfSaleEntity(A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(() => _fakeAzureQueueHelper.AddMessage(fakeRosEventJson)).MustNotHaveHappened(); @@ -389,8 +390,7 @@ public async Task WhenValidEventInLicenceUpdatedPublishedEventReceived_ThenWebho var result = (OkObjectResult)await _fakeWebHookController.LicenceUpdatedPublishedEventReceived(fakeLicenceUpdatedEventJson); - A.CallTo(() => _fakeAzureTableReaderWriter.UpsertLicenceUpdatedEntity(A.Ignored)).MustHaveHappenedOnceExactly(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateLicenceUpdatedEventStatus(A.Ignored)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappenedOnceExactly(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappenedTwiceExactly(); result.StatusCode.Should().Be(200); @@ -440,8 +440,7 @@ public async Task WhenCorrelationIdIsMissingInLicenceUpdatedPublishedEvent_ThenW result.StatusCode.Should().Be(400); - A.CallTo(() => _fakeAzureTableReaderWriter.UpsertLicenceUpdatedEntity(A.Ignored)).MustNotHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateLicenceUpdatedEventStatus(A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" @@ -475,9 +474,8 @@ public void WhenSapDoesNotRespond200Ok_ThenLicenceUpdatedWebhookReturns500Intern Assert.ThrowsAsync(() => _fakeWebHookController.LicenceUpdatedPublishedEventReceived(fakeLicenceUpdatedEventJson)); - A.CallTo(() => _fakeAzureTableReaderWriter.UpsertLicenceUpdatedEntity(A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateLicenceUpdatedEventStatus(A.Ignored)).MustNotHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Information diff --git a/tests/UKHO.ERPFacade.API.UnitTests/Helpers/EncContentSapMessageBuilderTests.cs b/tests/UKHO.ERPFacade.API.UnitTests/Helpers/EncContentSapMessageBuilderTests.cs index 59ac7cc1..758f4752 100644 --- a/tests/UKHO.ERPFacade.API.UnitTests/Helpers/EncContentSapMessageBuilderTests.cs +++ b/tests/UKHO.ERPFacade.API.UnitTests/Helpers/EncContentSapMessageBuilderTests.cs @@ -12,6 +12,7 @@ using NUnit.Framework; using UKHO.ERPFacade.API.Helpers; using UKHO.ERPFacade.API.UnitTests.Common; +using UKHO.ERPFacade.Common.Constants; using UKHO.ERPFacade.Common.Exceptions; using UKHO.ERPFacade.Common.IO; using UKHO.ERPFacade.Common.Logging; @@ -33,21 +34,6 @@ public class EncContentSapMessageBuilderTests private EncContentSapMessageBuilder _fakeEncContentSapMessageBuilder; private string _sapXmlTemplate; - private const string XpathActionItems = $"//*[local-name()='ACTIONITEMS']"; - private const string EncCell = "ENC CELL"; - private const string XpathProductName = $"//*[local-name()='PRODUCTNAME']"; - private const string XpathCorrection = $"//*[local-name()='CORRECTION']"; - private const string XpathWeekNo = $"//*[local-name()='WEEKNO']"; - private const string XpathValidFrom = $"//*[local-name()='VALIDFROM']"; - private const string XpathActiveKey = $"//*[local-name()='ACTIVEKEY']"; - private const string XpathNextKey = $"//*[local-name()='NEXTKEY']"; - private const string XpathChildCell = $"//*[local-name()='CHILDCELL']"; - private const string XpathReplacedBy = $"//*[local-name()='REPLACEDBY']"; - private const string XpathActionNumber = $"//*[local-name()='ACTIONNUMBER']"; - private const string XpathAction = $"//*[local-name()='ACTION']"; - private const string ReplaceEncCellAction = "REPLACED WITH ENC CELL"; - private const string ChangeEncCellAction = "CHANGE ENC CELL"; - [SetUp] public void Setup() { @@ -58,7 +44,7 @@ public void Setup() _fakeWeekDetailsProvider = A.Fake(); _fakePermitDecryption = A.Fake(); _fakeEncContentSapMessageBuilder = new EncContentSapMessageBuilder(_fakeLogger, _fakeXmlHelper, _fakeFileSystemHelper, _fakeSapActionConfig, _fakeWeekDetailsProvider, _fakePermitDecryption); - _sapXmlTemplate = TestHelper.ReadFileData("SapXmlTemplates\\SAPRequest.xml"); + _sapXmlTemplate = TestHelper.ReadFileData(Constants.S57SapXmlTemplatePath); } private IConfiguration InitConfiguration() @@ -271,15 +257,15 @@ public void SortXmlPayloadTest() var xmlDoc = new XmlDocument(); xmlDoc.LoadXml(sapReqXml); - var actionItemNode = xmlDoc.SelectSingleNode(XpathActionItems); + var actionItemNode = xmlDoc.SelectSingleNode(Constants.XpathActionItems); var sortedXmlPayLoad = typeof(EncContentSapMessageBuilder).GetMethod("SortXmlPayload", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)!; var result = (XmlNode)sortedXmlPayLoad.Invoke(_fakeEncContentSapMessageBuilder, new object[] { actionItemNode! })!; - var firstActionNumber = result.SelectSingleNode(XpathActionNumber); + var firstActionNumber = result.SelectSingleNode(Constants.XpathActionNumber); firstActionNumber.InnerXml.Should().Be(expectedActionNumber); - var firstActionName = result.SelectSingleNode(XpathAction); + var firstActionName = result.SelectSingleNode(Constants.XpathAction); firstActionName.InnerXml.Should().Be(expectedAction); } @@ -373,7 +359,7 @@ public void WhenUnitOfSaleIsNullWhileReplacingEncCell_ThenReturnsNull() { var cancelCellWithNewCellReplacementPayloadJson = TestHelper.ReadFileData("ERPTestData\\CancelCellWithNewCellReplacement.JSON"); var eventData = JsonConvert.DeserializeObject(cancelCellWithNewCellReplacementPayloadJson); - var action = _fakeSapActionConfig.Value.SapActions.FirstOrDefault(x => x.Product == EncCell && x.Action == ReplaceEncCellAction); + var action = _fakeSapActionConfig.Value.SapActions.FirstOrDefault(x => x.Product == Constants.EncCell && x.Action == Constants.ReplaceEncCellAction); MethodInfo buildAction = typeof(EncContentSapMessageBuilder).GetMethod("GetUnitOfSale", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)!; var result = (XmlElement)buildAction.Invoke(_fakeEncContentSapMessageBuilder, new object[] { action.ActionNumber, eventData.Data.UnitsOfSales!, eventData.Data.Products.FirstOrDefault()! })!; @@ -386,7 +372,7 @@ public void WhenUnitOfSaleIsNullWhileChangingEncCell_ThenReturnsNull() { var cancelCellWithNewCellReplacementPayloadJson = TestHelper.ReadFileData("ERPTestData\\CancelCellWithNewCellReplacement.JSON"); var eventData = JsonConvert.DeserializeObject(cancelCellWithNewCellReplacementPayloadJson); - var action = _fakeSapActionConfig.Value.SapActions.FirstOrDefault(x => x.Product == EncCell && x.Action == ChangeEncCellAction); + var action = _fakeSapActionConfig.Value.SapActions.FirstOrDefault(x => x.Product == Constants.EncCell && x.Action == Constants.ChangeEncCellAction); MethodInfo buildAction = typeof(EncContentSapMessageBuilder).GetMethod("GetUnitOfSale", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)!; var result = (XmlElement)buildAction.Invoke(_fakeEncContentSapMessageBuilder, new object[] { action.ActionNumber, eventData.Data.UnitsOfSales!, eventData.Data.Products.LastOrDefault()! })!; diff --git a/tests/UKHO.ERPFacade.CleanUp.WebJob.UnitTests/Services/CleanUpServiceTests.cs b/tests/UKHO.ERPFacade.CleanUp.WebJob.UnitTests/Services/CleanUpServiceTests.cs index ab5c0436..28835b11 100644 --- a/tests/UKHO.ERPFacade.CleanUp.WebJob.UnitTests/Services/CleanUpServiceTests.cs +++ b/tests/UKHO.ERPFacade.CleanUp.WebJob.UnitTests/Services/CleanUpServiceTests.cs @@ -1,4 +1,5 @@ -using FakeItEasy; +using Azure.Data.Tables; +using FakeItEasy; using FluentAssertions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -7,7 +8,6 @@ using UKHO.ERPFacade.Common.Configuration; using UKHO.ERPFacade.Common.IO.Azure; using UKHO.ERPFacade.Common.Logging; -using UKHO.ERPFacade.Common.Models.TableEntities; namespace UKHO.ERPFacade.CleanUp.WebJob.UnitTests.Services { @@ -20,8 +20,6 @@ public class CleanUpServiceTests private CleanUpService _fakeCleanUpService; private IOptions _fakeErpFacadeWebjobConfig; - private const string CompleteStatus = "Complete"; - [SetUp] public void Setup() { @@ -32,7 +30,7 @@ public void Setup() { CleanUpDurationInDays = "30" }); - _fakeCleanUpService = new CleanUpService(_fakeLogger, _fakeErpFacadeWebjobConfig, _fakeAzureTableReaderWriter,_fakeAzureBlobEventWriter); + _fakeCleanUpService = new CleanUpService(_fakeLogger, _fakeErpFacadeWebjobConfig, _fakeAzureTableReaderWriter, _fakeAzureBlobEventWriter); } [Test] @@ -69,150 +67,142 @@ public void Does_Constructor_Throws_ArgumentNullException_When_AzureBlobEventWri () => new CleanUpService(_fakeLogger, _fakeErpFacadeWebjobConfig, _fakeAzureTableReaderWriter, null)) .ParamName .Should().Be("azureBlobEventWriter"); - } + } [Test] public void WhenEESEventDataIsMoreForThanConfiguredDays_ThenDeleteRelatedTablesAndBlobs() - { - List eesEventData = new() + { + List eesEventData = new() { - new EESEventEntity() - { - CorrelationId = "corrid", - RequestDateTime = DateTime.Now.AddDays(-31), - PartitionKey = Guid.NewGuid().ToString(), - RowKey = Guid.NewGuid().ToString(), - Timestamp = DateTime.Now - } + new TableEntity() { + { "CorrelationId", "corrid" }, + { "RequestDateTime", DateTime.Now.AddDays(-31) }, + { "PartitionKey", Guid.NewGuid().ToString() }, + { "RowKey", Guid.NewGuid().ToString() }, + { "Timestamp", DateTime.Now } + } }; - - A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntityForEESTable()).Returns(eesEventData); + A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntities(A.Ignored)).Returns(eesEventData); _fakeCleanUpService.CleanUpAzureTableAndBlobs(); - - A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntityForEESTable()).MustHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.DeleteEESEntity(A.Ignored)).MustHaveHappened(); - A.CallTo(() => _fakeAzureBlobEventWriter.DeleteContainer(A.Ignored)).MustHaveHappened(); + + A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntities(A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.DeleteEntity(A.Ignored, A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeAzureBlobEventWriter.DeleteDirectory(A.Ignored, A.Ignored)).MustHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Information && call.GetArgument(1) == EventIds.FetchEESEntities.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Fetching all EES entities from azure table").MustHaveHappened(); + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Fetching all records from azure table {TableName}").MustHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Information && call.GetArgument(1) == EventIds.DeletedContainerSuccessful.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Deleting container : {0}").MustHaveHappened(); + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Deleting directory {CorrelationId} from {EventContainerName} container").MustHaveHappened(); } [Test] public void WhenRequestDateTimeisNull_ThenShouldNotDeleteRelatedTablesAndBlobs() - { - List eesEventData = new() + { + List eesEventData = new() { - new EESEventEntity() - { - CorrelationId = "corrid", - RequestDateTime = null, - PartitionKey= Guid.NewGuid().ToString(), - RowKey= Guid.NewGuid().ToString(), - Timestamp = DateTime.Now - } + new TableEntity() { + { "CorrelationId", "corrid" }, + { "RequestDateTime", null }, + { "PartitionKey", Guid.NewGuid().ToString() }, + { "RowKey", Guid.NewGuid().ToString() }, + { "Timestamp", DateTime.Now } + } }; - - A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntityForEESTable()).Returns(eesEventData); + + A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntities(A.Ignored)).Returns(eesEventData); _fakeCleanUpService.CleanUpAzureTableAndBlobs(); - - A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntityForEESTable()).MustHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.DeleteEESEntity(A.Ignored)).MustNotHaveHappened(); - A.CallTo(() => _fakeAzureBlobEventWriter.DeleteContainer(A.Ignored)).MustNotHaveHappened(); + + A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntities(A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.DeleteEntity(A.Ignored, A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureBlobEventWriter.DeleteDirectory(A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Information && call.GetArgument(1) == EventIds.FetchEESEntities.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Fetching all EES entities from azure table").MustHaveHappened(); + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Fetching all records from azure table {TableName}").MustHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Information && call.GetArgument(1) == EventIds.DeletedContainerSuccessful.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Deleting container : {0}").MustNotHaveHappened(); + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Deleting directory {CorrelationId} from {EventContainerName} container").MustNotHaveHappened(); } [Test] public void WhenEESEventDataIsWithinConfiguredDays_ThenShouldNotDeleteRelatedTablesAndBlobs() - { - List eesEventData = new() + { + List eesEventData = new() { - new EESEventEntity() - { - CorrelationId = "corrid", - RequestDateTime = DateTime.Now.AddDays(-21), - PartitionKey= Guid.NewGuid().ToString(), - RowKey= Guid.NewGuid().ToString(), - Timestamp = DateTime.Now - } + new TableEntity() { + { "CorrelationId", "corrid" }, + { "RequestDateTime", DateTime.Now.AddDays(-21) }, + { "PartitionKey", Guid.NewGuid().ToString() }, + { "RowKey", Guid.NewGuid().ToString() }, + { "Timestamp", DateTime.Now } + } }; - - A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntityForEESTable()).Returns(eesEventData); + A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntities(A.Ignored)).Returns(eesEventData); _fakeCleanUpService.CleanUpAzureTableAndBlobs(); - - A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntityForEESTable()).MustHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.DeleteEESEntity(A.Ignored)).MustNotHaveHappened(); - A.CallTo(() => _fakeAzureBlobEventWriter.DeleteContainer(A.Ignored)).MustNotHaveHappened(); + + A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntities(A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.DeleteEntity(A.Ignored, A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureBlobEventWriter.DeleteDirectory(A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Information && call.GetArgument(1) == EventIds.FetchEESEntities.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Fetching all EES entities from azure table").MustHaveHappened(); + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Fetching all records from azure table {TableName}").MustHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Information && call.GetArgument(1) == EventIds.DeletedContainerSuccessful.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Deleting container : {0}").MustNotHaveHappened(); + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Deleting directory {CorrelationId} from {EventContainerName} container").MustNotHaveHappened(); } [Test] public void WhenEESEventDataIsEqualConfiguredDays_ThenShouldNotDeleteRelatedTablesAndBlobs() - { - List eesEventData = new() + { + List eesEventData = new() { - new EESEventEntity() - { - CorrelationId = "corrid", - RequestDateTime = DateTime.Now.AddDays(-30), - PartitionKey= Guid.NewGuid().ToString(), - RowKey= Guid.NewGuid().ToString(), - Timestamp = DateTime.Now - } + new TableEntity() { + { "CorrelationId", "corrid" }, + { "RequestDateTime", DateTime.Now.AddDays(-30) }, + { "PartitionKey", Guid.NewGuid().ToString() }, + { "RowKey", Guid.NewGuid().ToString() }, + { "Timestamp", DateTime.Now } + } }; - - A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntityForEESTable()).Returns(eesEventData); + A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntities(A.Ignored)).Returns(eesEventData); _fakeCleanUpService.CleanUpAzureTableAndBlobs(); - - A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntityForEESTable()).MustHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.DeleteEESEntity(A.Ignored)).MustNotHaveHappened(); - A.CallTo(() => _fakeAzureBlobEventWriter.DeleteContainer(A.Ignored)).MustNotHaveHappened(); + + A.CallTo(() => _fakeAzureTableReaderWriter.GetAllEntities(A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.DeleteEntity(A.Ignored, A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureBlobEventWriter.DeleteDirectory(A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Information && call.GetArgument(1) == EventIds.FetchEESEntities.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Fetching all EES entities from azure table").MustHaveHappened(); + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Fetching all records from azure table {TableName}").MustHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Information && call.GetArgument(1) == EventIds.DeletedContainerSuccessful.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Deleting container : {0}").MustNotHaveHappened(); - + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Deleting directory {CorrelationId} from {EventContainerName} container").MustNotHaveHappened(); } } } diff --git a/tests/UKHO.ERPFacade.EventAggregation.WebJob.UnitTests/Services/AggregationServiceTests.cs b/tests/UKHO.ERPFacade.EventAggregation.WebJob.UnitTests/Services/AggregationServiceTests.cs index 1ea27e01..0e9c9497 100644 --- a/tests/UKHO.ERPFacade.EventAggregation.WebJob.UnitTests/Services/AggregationServiceTests.cs +++ b/tests/UKHO.ERPFacade.EventAggregation.WebJob.UnitTests/Services/AggregationServiceTests.cs @@ -16,6 +16,7 @@ using System.Xml; using UKHO.ERPFacade.Common.Exceptions; using UKHO.ERPFacade.Common.Models; +using Azure.Data.Tables; namespace UKHO.ERPFacade.EventAggregation.WebJob.UnitTests.Services { @@ -94,14 +95,21 @@ public async Task WhenRecordOfSaleEntityStatusIsComplete_ThenShouldNotMerge() "{\"type\":\"uk.gov.ukho.shop.recordOfSale.v1\",\"eventId\":\"ad5b0ca4-2668-4345-9699-49d8f2c5a006\",\"correlationId\":\"999ce4a4-1d62-4f56-b359-59e178d77003\",\"relatedEvents\":[\"e744fa37-0c9f-4795-adc9-7f42ad8f005\",\"ad5b0ca4-2668-4345-9699-49d8f2c5a006\"],\"transactionType\":\"NEWLICENCE\"}"; QueueMessage queueMessage = QueuesModelFactory.QueueMessage("12345", "pr1", messageText, 1, DateTimeOffset.UtcNow); + TableEntity entity = new TableEntity(){ + { "CorrelationId", "corrid" }, + { "Status", "Complete"}, + { "PartitionKey", Guid.NewGuid().ToString() }, + { "RowKey", Guid.NewGuid().ToString() }, + { "Timestamp", DateTime.Now } + }; - A.CallTo(() => _fakeAzureTableReaderWriter.GetEntityStatus(A.Ignored)).Returns("Complete"); + A.CallTo(() => _fakeAzureTableReaderWriter.GetEntity(A.Ignored, A.Ignored)).Returns(entity); await _fakeAggregationService.MergeRecordOfSaleEvents(queueMessage); A.CallTo(() => _fakeAzureBlobEventWriter.GetBlobNamesInFolder(A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.DownloadEvent(A.Ignored, A.Ignored)).MustNotHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateRecordOfSaleEventStatus(A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpdateEntity(A.Ignored, A.Ignored, A[]>.Ignored)).MustNotHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" @@ -123,15 +131,22 @@ public async Task WhenAllRelatedEventsNotFoundInBlob_ThenShouldNotMerge() QueueMessage queueMessage = QueuesModelFactory.QueueMessage("12345", "pr1", messageText, 1, DateTimeOffset.UtcNow); RecordOfSaleQueueMessageEntity message = JsonConvert.DeserializeObject(queueMessage.Body.ToString())!; - - A.CallTo(() => _fakeAzureTableReaderWriter.GetEntityStatus(A.Ignored)).Returns("Incomplete"); + TableEntity entity = new TableEntity(){ + { "CorrelationId", "corrid" }, + { "Status", "Incomplete"}, + { "PartitionKey", Guid.NewGuid().ToString() }, + { "RowKey", Guid.NewGuid().ToString() }, + { "Timestamp", DateTime.Now } + }; + + A.CallTo(() => _fakeAzureTableReaderWriter.GetEntity(A.Ignored, A.Ignored)).Returns(entity); A.CallTo(() => _fakeAzureBlobEventWriter.GetBlobNamesInFolder(A.Ignored, A.Ignored)).Returns(blob); await _fakeAggregationService.MergeRecordOfSaleEvents(queueMessage); A.CallTo(() => _fakeAzureBlobEventWriter.GetBlobNamesInFolder(A.Ignored, A.Ignored)).MustHaveHappenedOnceExactly(); A.CallTo(() => _fakeAzureBlobEventWriter.DownloadEvent(A.Ignored, A.Ignored)).MustNotHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateRecordOfSaleEventStatus(A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpdateEntity(A.Ignored, A.Ignored, A[]>.Ignored)).MustNotHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" @@ -155,8 +170,15 @@ public void WhenSapDoesNotRespond200Ok_ThenWebJobReturns500InternalServerRespons QueueMessage queueMessage = QueuesModelFactory.QueueMessage("12345", "pr1", messageText, 1, DateTimeOffset.UtcNow); RecordOfSaleQueueMessageEntity message = JsonConvert.DeserializeObject(queueMessage.Body.ToString())!; - - A.CallTo(() => _fakeAzureTableReaderWriter.GetEntityStatus(A.Ignored)).Returns("Incomplete"); + TableEntity entity = new TableEntity(){ + { "CorrelationId", "corrid" }, + { "Status", "Incomplete"}, + { "PartitionKey", Guid.NewGuid().ToString() }, + { "RowKey", Guid.NewGuid().ToString() }, + { "Timestamp", DateTime.Now } + }; + + A.CallTo(() => _fakeAzureTableReaderWriter.GetEntity(A.Ignored, A.Ignored)).Returns(entity); A.CallTo(() => _fakeAzureBlobEventWriter.GetBlobNamesInFolder(A.Ignored, A.Ignored)).Returns(blob); A.CallTo(() => @@ -174,7 +196,7 @@ public void WhenSapDoesNotRespond200Ok_ThenWebJobReturns500InternalServerRespons A.CallTo(() => _fakeAzureBlobEventWriter.GetBlobNamesInFolder(A.Ignored, A.Ignored)).MustHaveHappenedOnceExactly(); A.CallTo(() => _fakeAzureBlobEventWriter.DownloadEvent(A.Ignored, A.Ignored)).MustHaveHappenedOnceOrMore(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateRecordOfSaleEventStatus(A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpdateEntity(A.Ignored, A.Ignored, A[]>.Ignored)).MustNotHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappenedOnceExactly(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" @@ -208,8 +230,15 @@ public async Task WhenRecordOfSaleEventReceived_ThenShouldMergeEvents() QueueMessage queueMessage = QueuesModelFactory.QueueMessage("12345", "pr1", messageText, 1, DateTimeOffset.UtcNow); RecordOfSaleQueueMessageEntity message = JsonConvert.DeserializeObject(queueMessage.Body.ToString())!; - - A.CallTo(() => _fakeAzureTableReaderWriter.GetEntityStatus(A.Ignored)).Returns("Incomplete"); + TableEntity entity = new TableEntity(){ + { "CorrelationId", "corrid" }, + { "Status", "Incomplete"}, + { "PartitionKey", Guid.NewGuid().ToString() }, + { "RowKey", Guid.NewGuid().ToString() }, + { "Timestamp", DateTime.Now } + }; + + A.CallTo(() => _fakeAzureTableReaderWriter.GetEntity(A.Ignored, A.Ignored)).Returns(entity); A.CallTo(() => _fakeAzureBlobEventWriter.GetBlobNamesInFolder(A.Ignored, A.Ignored)).Returns(blob); A.CallTo(() => @@ -227,7 +256,7 @@ public async Task WhenRecordOfSaleEventReceived_ThenShouldMergeEvents() A.CallTo(() => _fakeAzureBlobEventWriter.GetBlobNamesInFolder(A.Ignored, A.Ignored)).MustHaveHappenedOnceExactly(); A.CallTo(() => _fakeAzureBlobEventWriter.DownloadEvent(A.Ignored, A.Ignored)).MustHaveHappenedOnceOrMore(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateRecordOfSaleEventStatus(A.Ignored)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _fakeAzureTableReaderWriter.UpdateEntity(A.Ignored, A.Ignored, A[]>.Ignored)).MustHaveHappened(); A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappenedOnceExactly(); A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" @@ -266,8 +295,15 @@ public void WhenValidateEntityThrowsException_ThenThrowsException() QueueMessage queueMessage = QueuesModelFactory.QueueMessage("12345", "pr1", messageText, 1, DateTimeOffset.UtcNow); RecordOfSaleQueueMessageEntity message = JsonConvert.DeserializeObject(queueMessage.Body.ToString())!; - - A.CallTo(() => _fakeAzureTableReaderWriter.GetEntityStatus(A.Ignored)).Returns("Incomplete"); + TableEntity entity = new TableEntity(){ + { "CorrelationId", "corrid" }, + { "Status", "Incomplete"}, + { "PartitionKey", Guid.NewGuid().ToString() }, + { "RowKey", Guid.NewGuid().ToString() }, + { "Timestamp", DateTime.Now } + }; + + A.CallTo(() => _fakeAzureTableReaderWriter.GetEntity(A.Ignored, A.Ignored)).Returns(entity); A.CallTo(() => _fakeAzureBlobEventWriter.GetBlobNamesInFolder(A.Ignored, A.Ignored)).Returns(blob); A.CallTo(() => From 5a65c5f7a9de9b17c4414ce5381933f9338ebb98 Mon Sep 17 00:00:00 2001 From: rushdynajath Date: Thu, 17 Oct 2024 15:49:57 +0100 Subject: [PATCH 7/8] Merge main into dev17 10 (#219) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump System.Runtime.Caching in /src/UKHO.ERPFacade.Common (#199) Bumps [System.Runtime.Caching](https://github.com/dotnet/runtime) from 8.0.0 to 8.0.1. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) --- updated-dependencies: - dependency-name: System.Runtime.Caching dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump the all-packages group with 4 updates (#196) * Bump the all-packages group with 4 updates Bumps the all-packages group with 4 updates: [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore), [SoapCore](https://github.com/DigDes/SoapCore), [RestSharp](https://github.com/restsharp/RestSharp) and [WireMock.Net](https://github.com/WireMock-Net/WireMock.Net). Updates `Swashbuckle.AspNetCore` from 6.8.0 to 6.8.1 - [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases) - [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.8.0...v6.8.1) Updates `SoapCore` from 1.1.0.49 to 1.1.0.51 - [Release notes](https://github.com/DigDes/SoapCore/releases) - [Commits](https://github.com/DigDes/SoapCore/compare/v1.1.0.49...v1.1.0.51) Updates `RestSharp` from 112.0.0 to 112.1.0 - [Release notes](https://github.com/restsharp/RestSharp/releases) - [Commits](https://github.com/restsharp/RestSharp/compare/112.0.0...112.1.0) Updates `WireMock.Net` from 1.6.5 to 1.6.6 - [Release notes](https://github.com/WireMock-Net/WireMock.Net/releases) - [Changelog](https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md) - [Commits](https://github.com/WireMock-Net/WireMock.Net/compare/1.6.5...1.6.6) --- updated-dependencies: - dependency-name: Swashbuckle.AspNetCore dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: SoapCore dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: RestSharp dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-packages - dependency-name: WireMock.Net dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages ... Signed-off-by: dependabot[bot] * Add suppression for CVE-2024-43483 in System.Runtime.Caching * Add suppression for CVE-2022-34716 in System.Security.Cryptography.Xml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: HugoBurgess <128484816+HugoBurgess@users.noreply.github.com> Co-authored-by: rushdynajath * Bump System.Text.Json from 8.0.4 to 8.0.5 in /src/UKHO.ERPFacade.API (#200) Bumps [System.Text.Json](https://github.com/dotnet/runtime) from 8.0.4 to 8.0.5. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) --- updated-dependencies: - dependency-name: System.Text.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump System.Text.Json in /src/UKHO.ERPFacade.CleanUp.WebJob (#207) Bumps [System.Text.Json](https://github.com/dotnet/runtime) from 8.0.4 to 8.0.5. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) --- updated-dependencies: - dependency-name: System.Text.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Refactor Azure Pipelines YAML to streamline permit configuration vari… (#211) * Refactor Azure Pipelines YAML to streamline permit configuration variables * Add PermitDecryptionHardwareId to Azure Pipelines configuration * Bump the all-packages group with 20 updates (#212) Bumps the all-packages group with 20 updates: | Package | From | To | | --- | --- | --- | | [Elastic.Apm.NetCoreAll](https://github.com/elastic/apm-agent-dotnet) | `1.29.0` | `1.30.0` | | [Microsoft.AspNetCore.Authentication.JwtBearer](https://github.com/dotnet/aspnetcore) | `6.0.33` | `6.0.35` | | [Microsoft.AspNetCore.HeaderPropagation](https://github.com/dotnet/aspnetcore) | `6.0.33` | `6.0.35` | | [Microsoft.AspNetCore.Mvc.NewtonsoftJson](https://github.com/dotnet/aspnetcore) | `6.0.33` | `6.0.35` | | [Microsoft.Extensions.Diagnostics.HealthChecks](https://github.com/dotnet/aspnetcore) | `8.0.8` | `8.0.10` | | [Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions](https://github.com/dotnet/aspnetcore) | `8.0.8` | `8.0.10` | | [Microsoft.Extensions.Logging.Abstractions](https://github.com/dotnet/runtime) | `8.0.1` | `8.0.2` | | [Microsoft.Extensions.Logging.AzureAppServices](https://github.com/dotnet/aspnetcore) | `8.0.8` | `8.0.10` | | [Microsoft.Extensions.Configuration.Json](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [System.Text.Json](https://github.com/dotnet/runtime) | `8.0.4` | `8.0.5` | | [Microsoft.Extensions.Logging](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [Microsoft.Extensions.DependencyInjection](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [Microsoft.Extensions.Logging.Console](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [Microsoft.Extensions.Logging.Debug](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [Azure.Storage.Blobs](https://github.com/Azure/azure-sdk-for-net) | `12.22.1` | `12.22.2` | | [Azure.Storage.Queues](https://github.com/Azure/azure-sdk-for-net) | `12.20.0` | `12.20.1` | | [Microsoft.Extensions.Http](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | | [Microsoft.Extensions.Http.Polly](https://github.com/dotnet/aspnetcore) | `8.0.8` | `8.0.10` | | [Microsoft.Azure.WebJobs.Extensions.Storage](https://github.com/Azure/azure-sdk-for-net) | `5.3.2` | `5.3.3` | | [Microsoft.Extensions.Hosting](https://github.com/dotnet/runtime) | `8.0.0` | `8.0.1` | Updates `Elastic.Apm.NetCoreAll` from 1.29.0 to 1.30.0 - [Release notes](https://github.com/elastic/apm-agent-dotnet/releases) - [Changelog](https://github.com/elastic/apm-agent-dotnet/blob/main/CHANGELOG.asciidoc) - [Commits](https://github.com/elastic/apm-agent-dotnet/compare/v1.29.0...v1.30.0) Updates `Microsoft.AspNetCore.Authentication.JwtBearer` from 6.0.33 to 6.0.35 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v6.0.33...v6.0.35) Updates `Microsoft.AspNetCore.HeaderPropagation` from 6.0.33 to 6.0.35 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v6.0.33...v6.0.35) Updates `Microsoft.AspNetCore.Mvc.NewtonsoftJson` from 6.0.33 to 6.0.35 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v6.0.33...v6.0.35) Updates `Microsoft.Extensions.Diagnostics.HealthChecks` from 8.0.8 to 8.0.10 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v8.0.8...v8.0.10) Updates `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions` from 8.0.8 to 8.0.10 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v8.0.8...v8.0.10) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions` from 8.0.8 to 8.0.10 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v8.0.8...v8.0.10) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging.AzureAppServices` from 8.0.8 to 8.0.10 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v8.0.8...v8.0.10) Updates `Microsoft.Extensions.Configuration.Json` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `System.Text.Json` from 8.0.4 to 8.0.5 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging.Console` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `System.Text.Json` from 8.0.4 to 8.0.5 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) Updates `System.Text.Json` from 8.0.4 to 8.0.5 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) Updates `Microsoft.Extensions.Configuration.Json` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `System.Text.Json` from 8.0.4 to 8.0.5 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Debug` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Azure.Storage.Blobs` from 12.22.1 to 12.22.2 - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Storage.Blobs_12.22.1...Azure.Storage.Blobs_12.22.2) Updates `Azure.Storage.Queues` from 12.20.0 to 12.20.1 - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Storage.Queues_12.20.0...Azure.Storage.Queues_12.20.1) Updates `Microsoft.Extensions.Http` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Http.Polly` from 8.0.8 to 8.0.10 - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v8.0.8...v8.0.10) Updates `Microsoft.Extensions.Http` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Azure.WebJobs.Extensions.Storage` from 5.3.2 to 5.3.3 - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Microsoft.Azure.WebJobs.Extensions.Storage_5.3.2...Microsoft.Azure.WebJobs.Extensions.Storage_5.3.3) Updates `Microsoft.Extensions.Hosting` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Configuration.Json` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `System.Text.Json` from 8.0.4 to 8.0.5 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5) Updates `Microsoft.Extensions.DependencyInjection` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Abstractions` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v8.0.2) Updates `Microsoft.Extensions.Logging` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Console` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) Updates `Microsoft.Extensions.Logging.Debug` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0...v8.0.1) --- updated-dependencies: - dependency-name: Elastic.Apm.NetCoreAll dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-packages - dependency-name: Microsoft.AspNetCore.Authentication.JwtBearer dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.AspNetCore.HeaderPropagation dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.AspNetCore.Mvc.NewtonsoftJson dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Diagnostics.HealthChecks dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.AzureAppServices dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Configuration.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Console dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Configuration.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Debug dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Azure.Storage.Blobs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Azure.Storage.Queues dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Http dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Http.Polly dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Http dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Azure.WebJobs.Extensions.Storage dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Hosting dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Configuration.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Console dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages - dependency-name: Microsoft.Extensions.Logging.Debug dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-packages ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Release/pipeline prod (#218) * Add dependency on PreProdDeploy stage for Livedeploy * Add Permit Decryption Hardware ID and Azure AD configurations to pipeline * update main * Refactor Azure Pipelines YAML to remove unused variable for EnterpriseEventServiceConfiguration * Update NVDSuppressions.xml add suppression * Update NVDSuppressions.xml add suppression * Update NVDSuppressions.xml remove zero match * Update NVDSuppressions.xml remove zero referane --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: HugoBurgess <128484816+HugoBurgess@users.noreply.github.com> --- NVDSuppressions.xml | 63 +++++++++++++++++++++++++++++++++++++++++++++ azure-pipelines.yml | 25 ++++++++++++++++-- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/NVDSuppressions.xml b/NVDSuppressions.xml index a3ee45bd..3bc7f28b 100644 --- a/NVDSuppressions.xml +++ b/NVDSuppressions.xml @@ -796,4 +796,67 @@ ^pkg:nuget/System\.Security\.Cryptography\.Xml@.*$ CVE-2022-34716 + + + ^pkg:nuget/System\.Security\.Cryptography\.Xml@.*$ + CVE-2022-34716 + + + + + + ^pkg:generic/Azure\.Core@.*$ + CVE-2024-43591 + + + + + + ^pkg:nuget/Azure\.Core@.*$ + CVE-2024-43591 + + + + + + ^pkg:nuget/Azure\.Identity@.*$ + CVE-2024-43591 + + + + + + + ^pkg:nuget/Microsoft\.Extensions\.Azure@.*$ + CVE-2024-43591 + + + + + + ^pkg:generic/System\.ClientModel@.*$ + CVE-2024-43591 + + + + + + ^pkg:generic/Microsoft\.Extensions\.Azure@.*$ + CVE-2024-43591 + + diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 68381954..36179514 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -632,7 +632,9 @@ stages: - name: "AzureADConfiguration.ClientSecretNoRole" value: $(AzureADConfigurationClientSecretNoRole) - name: "EnterpriseEventServiceConfiguration.ClientId" - value: $(EnterpriseEventServiceConfigurationClientId) + value: $(EnterpriseEventServiceConfigurationClientId) + - name: "PermitConfiguration.PermitDecryptionHardwareId" + value: $(PermitDecryptionHardwareId) - name: mockWebAppName value: $[ stageDependencies.DevDeploy.DevDeployTerraform.outputs['DevDeployTerraform.TerraformDeploy.mockWebApp'] ] - name: mockWebAppResourceGroup @@ -866,6 +868,7 @@ stages: AzureSubscription: "ERP-Facade-Dev-A.011.05.12" - stage: Livedeploy + dependsOn: PreProdDeploy displayName: "Livedeploy (inc terraform, webapp deploy)" variables: - group: "ERP-Facade-Live" @@ -874,8 +877,26 @@ stages: value: $(AzureADConfigurationTenantId) - name: "AzureADConfiguration.ClientId" value: $(AzureADConfigurationClientId) + - name: "AzureADConfiguration.AutoTestClientId" + value: $(AzureADConfigurationAutoTestClientId) + - name: "AzureADConfiguration.ClientSecret" + value: $(AzureADConfigurationClientSecret) + - name: "AzureADConfiguration.AutoTestClientIdNoRole" + value: $(AzureADConfigurationAutoTestClientIdNoRole) + - name: "AzureADConfiguration.ClientSecretNoRole" + value: $(AzureADConfigurationClientSecretNoRole) - name: "EnterpriseEventServiceConfiguration.ClientId" - value: $(EnterpriseEventServiceConfigurationClientId) + value: $(EnterpriseEventServiceConfigurationClientId) + - name: "AzureADConfiguration.AutoTestClientId" + value: $(AzureADConfigurationAutoTestClientId) + - name: "AzureADConfiguration.ClientSecret" + value: $(AzureADConfigurationClientSecret) + - name: "AzureADConfiguration.AutoTestClientIdNoRole" + value: $(AzureADConfigurationAutoTestClientIdNoRole) + - name: "AzureADConfiguration.ClientSecretNoRole" + value: $(AzureADConfigurationClientSecretNoRole) + - name: "PermitConfiguration.PermitDecryptionHardwareId" + value: $(PermitDecryptionHardwareId) condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'),startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'))) jobs: - deployment: LiveDeployTerraform From f0ff8174d643b081576d73cb463bf9fccf61b54b Mon Sep 17 00:00:00 2001 From: Pooja More <135319691+pooja15131@users.noreply.github.com> Date: Thu, 17 Oct 2024 21:22:43 +0530 Subject: [PATCH 8/8] 181622 exclude aio cells (#217) * 181622 - development & UTs to exclude aio cells from erp facade newenccontentpublishedeventreceived s57 processing. * 181622 - AIO Test data file renamed And UTs added with new test data files for stryker coverage improvment. * 181622-Added FTs for AIO scenarios- AB#181622 * 181622-Added constant for AIO-AB#181622 * 181623-code refactored for stryker AB#181623 * 181622 - UT added to improve stryker coverage * 181622-removed unused namespace AB#181622 * 181623-code refactored for stryker improvement AB#181623 * 181622-code refactored for aio cell AB#181622 * 181622-removed scenario for mixed cell payload AB#181622 * 181622-log updated AB#181622 * 181622-removed sucess status code from log AB#181622 --------- Co-authored-by: Pooja More Co-authored-by: rushikeshkhopatkar Co-authored-by: Pravin Varade Co-authored-by: Vishal Dukare Co-authored-by: rushdynajath --- .../Controllers/WebhookController.cs | 39 +- .../Helpers/EncContentSapMessageBuilder.cs | 54 +- src/UKHO.ERPFacade.API/Program.cs | 3 + .../Services/IS57Service.cs | 9 + src/UKHO.ERPFacade.API/Services/S57Service.cs | 99 + .../UKHO.ERPFacade.API.csproj | 6 - src/UKHO.ERPFacade.API/appsettings.json | 3 + .../Configuration/AioConfiguration.cs | 10 + .../Constants/Constants.cs | 4 +- src/UKHO.ERPFacade.Common/Logging/EventIds.cs | 12 +- .../ERPFacadePayloadTestData/AIONewCell.JSON | 2897 +++++++++++++++++ .../AIOUpdateCell.JSON | 87 + .../FunctionalTests/WebhookScenarios.cs | 4 + .../Service/S57WebhookEndpoint.cs | 5 + .../UKHO.ERPFacade.API.FunctionalTests.csproj | 6 + .../Controllers/WebhookControllerTests.cs | 95 +- .../ERPTestData/NewAIOCell.JSON | 82 + ...llWithNullYearInUkhoWeekNumberSection.JSON | 139 + ...lphaCorrectionInUkhoWeekNumberSection.JSON | 138 + ...ellWithoutYearInUkhoWeekNumberSection.JSON | 138 + .../EncContentSapMessageBuilderTests.cs | 43 + .../Services/S57ServiceTests.cs | 180 + .../UKHO.ERPFacade.API.UnitTests.csproj | 12 + 23 files changed, 3897 insertions(+), 168 deletions(-) create mode 100644 src/UKHO.ERPFacade.API/Services/IS57Service.cs create mode 100644 src/UKHO.ERPFacade.API/Services/S57Service.cs create mode 100644 src/UKHO.ERPFacade.Common/Configuration/AioConfiguration.cs create mode 100644 tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadePayloadTestData/AIONewCell.JSON create mode 100644 tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadePayloadTestData/AIOUpdateCell.JSON create mode 100644 tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewAIOCell.JSON create mode 100644 tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithNullYearInUkhoWeekNumberSection.JSON create mode 100644 tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithNullcurrentWeekAlphaCorrectionInUkhoWeekNumberSection.JSON create mode 100644 tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithoutYearInUkhoWeekNumberSection.JSON create mode 100644 tests/UKHO.ERPFacade.API.UnitTests/Services/S57ServiceTests.cs diff --git a/src/UKHO.ERPFacade.API/Controllers/WebhookController.cs b/src/UKHO.ERPFacade.API/Controllers/WebhookController.cs index 1dd21e67..ea50cf89 100644 --- a/src/UKHO.ERPFacade.API/Controllers/WebhookController.cs +++ b/src/UKHO.ERPFacade.API/Controllers/WebhookController.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UKHO.ERPFacade.API.Helpers; +using UKHO.ERPFacade.API.Services; using UKHO.ERPFacade.Common.Configuration; using UKHO.ERPFacade.Common.Constants; using UKHO.ERPFacade.Common.Exceptions; @@ -27,7 +28,7 @@ public class WebhookController : BaseController private readonly IAzureBlobEventWriter _azureBlobEventWriter; private readonly IAzureQueueHelper _azureQueueHelper; private readonly ISapClient _sapClient; - private readonly IEncContentSapMessageBuilder _encContentSapMessageBuilder; + private readonly IS57Service _s57Service; private readonly IOptions _sapConfig; private readonly ILicenceUpdatedSapMessageBuilder _licenceUpdatedSapMessageBuilder; @@ -37,7 +38,7 @@ public WebhookController(IHttpContextAccessor contextAccessor, IAzureBlobEventWriter azureBlobEventWriter, IAzureQueueHelper azureQueueHelper, ISapClient sapClient, - IEncContentSapMessageBuilder encContentSapMessageBuilder, + IS57Service s57Service, IOptions sapConfig, ILicenceUpdatedSapMessageBuilder licenceUpdatedSapMessageBuilder) : base(contextAccessor) @@ -47,7 +48,7 @@ public WebhookController(IHttpContextAccessor contextAccessor, _azureBlobEventWriter = azureBlobEventWriter; _azureQueueHelper = azureQueueHelper; _sapClient = sapClient; - _encContentSapMessageBuilder = encContentSapMessageBuilder; + _s57Service = s57Service; _licenceUpdatedSapMessageBuilder = licenceUpdatedSapMessageBuilder; _sapConfig = sapConfig ?? throw new ArgumentNullException(nameof(sapConfig)); } @@ -84,37 +85,7 @@ public virtual async Task NewEncContentPublishedEventReceived([Fr return new BadRequestObjectResult(StatusCodes.Status400BadRequest); } - EncEventEntity encEventEntity = new() - { - RowKey = Guid.NewGuid().ToString(), - PartitionKey = Guid.NewGuid().ToString(), - Timestamp = DateTime.UtcNow, - CorrelationId = correlationId, - RequestDateTime = null - }; - - _logger.LogInformation(EventIds.AddingEntryForEncContentPublishedEventInAzureTable.ToEventId(), "Adding/Updating entry for enccontentpublished event in azure table."); - await _azureTableReaderWriter.UpsertEntity(correlationId, Constants.S57EventTableName, encEventEntity); - - _logger.LogInformation(EventIds.UploadEncContentPublishedEventInAzureBlobStarted.ToEventId(), "Uploading enccontentpublished event payload in blob storage."); - await _azureBlobEventWriter.UploadEvent(encEventJson.ToString(), Constants.S57EventContainerName, correlationId + '/' + Constants.S57EncEventFileName); - _logger.LogInformation(EventIds.UploadEncContentPublishedEventInAzureBlobCompleted.ToEventId(), "The enccontentpublished event payload is uploaded in blob storage successfully."); - - var sapPayload = _encContentSapMessageBuilder.BuildSapMessageXml(JsonConvert.DeserializeObject(encEventJson.ToString())); - - _logger.LogInformation(EventIds.UploadSapXmlPayloadInAzureBlobStarted.ToEventId(), "Uploading the SAP XML payload in blob storage."); - await _azureBlobEventWriter.UploadEvent(sapPayload.ToIndentedString(), Constants.S57EventContainerName, correlationId + '/' + Constants.SapXmlPayloadFileName); - _logger.LogInformation(EventIds.UploadSapXmlPayloadInAzureBlobCompleted.ToEventId(), "SAP XML payload is uploaded in blob storage successfully."); - - var response = await _sapClient.PostEventData(sapPayload, _sapConfig.Value.SapEndpointForEncEvent, _sapConfig.Value.SapServiceOperationForEncEvent, _sapConfig.Value.SapUsernameForEncEvent, _sapConfig.Value.SapPasswordForEncEvent); - - if (!response.IsSuccessStatusCode) - { - throw new ERPFacadeException(EventIds.RequestToSapFailed.ToEventId(), $"An error occurred while sending a request to SAP. | {response.StatusCode}"); - } - _logger.LogInformation(EventIds.EncUpdateSentToSap.ToEventId(), "ENC update has been sent to SAP successfully. | {StatusCode}", response.StatusCode); - - await _azureTableReaderWriter.UpdateEntity(correlationId, Constants.S57EventTableName, new[] { new KeyValuePair("RequestDateTime", DateTime.UtcNow) }); + await _s57Service.ProcessS57Event(encEventJson); return new OkObjectResult(StatusCodes.Status200OK); } diff --git a/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs b/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs index e6893565..968ec282 100644 --- a/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs +++ b/src/UKHO.ERPFacade.API/Helpers/EncContentSapMessageBuilder.cs @@ -61,9 +61,16 @@ public XmlDocument BuildSapMessageXml(EncEventPayload eventData) // Build SAP actions for Units BuildUnitActions(eventData, soapXml, actionItemNode); + + var xmlNode = SortXmlPayload(actionItemNode); + + soapXml.SelectSingleNode(Constants.XpathCorrId).InnerText = eventData.Data.CorrelationId; + soapXml.SelectSingleNode(Constants.XpathNoOfActions).InnerText = xmlNode.ChildNodes.Count.ToString(); + soapXml.SelectSingleNode(Constants.XpathRecDate).InnerText = DateTime.UtcNow.ToString(Constants.RecDateFormat); + soapXml.SelectSingleNode(Constants.XpathRecTime).InnerText = DateTime.UtcNow.ToString(Constants.RecTimeFormat); - // Finalize SAP XML message - FinalizeSapXmlMessage(soapXml, eventData.Data.CorrelationId, actionItemNode); + var IM_MATINFONode = soapXml.SelectSingleNode(Constants.XpathImMatInfo); + IM_MATINFONode.AppendChild(xmlNode); _logger.LogInformation(EventIds.GenerationOfSapXmlPayloadCompleted.ToEventId(), "Generation of SAP XML payload completed."); @@ -156,20 +163,7 @@ private void BuildUnitActions(EncEventPayload eventData, XmlDocument soapXml, Xm } } } - - private void FinalizeSapXmlMessage(XmlDocument soapXml, string correlationId, XmlNode actionItemNode) - { - var xmlNode = SortXmlPayload(actionItemNode); - - SetXmlNodeValue(soapXml, Constants.XpathCorrId, correlationId); - SetXmlNodeValue(soapXml, Constants.XpathNoOfActions, xmlNode.ChildNodes.Count.ToString()); - SetXmlNodeValue(soapXml, Constants.XpathRecDate, DateTime.UtcNow.ToString(Constants.RecDateFormat)); - SetXmlNodeValue(soapXml, Constants.XpathRecTime, DateTime.UtcNow.ToString(Constants.RecTimeFormat)); - - var IM_MATINFONode = soapXml.SelectSingleNode(Constants.XpathImMatInfo); - IM_MATINFONode.AppendChild(xmlNode); - } - + /// /// Returns primary unit of sale for given product to get ProductName for ENC cell SAP actions. /// @@ -287,7 +281,7 @@ private XmlElement BuildAction(XmlDocument soapXml, Product product, UnitOfSale private void AppendChildNode(XmlElement parentNode, XmlDocument doc, string nodeName, string value) { var childNode = doc.CreateElement(nodeName); - childNode.InnerText = value ?? string.Empty; + childNode.InnerText = value; parentNode.AppendChild(childNode); } @@ -358,7 +352,7 @@ private void ProcessUkhoWeekNumberAttributes(string action, IEnumerable Convert.ToInt32(node.SelectSingleNode(Constants.ActionNumber)?.InnerText ?? "0")) + .OrderBy(node => Convert.ToInt32(node.SelectSingleNode(Constants.ActionNumber)?.InnerText)) .ToList(); // Update the sequence number in the sorted list foreach (XmlNode actionItem in sortedActionItems) { - var actionNumberNode = actionItem.SelectSingleNode(Constants.ActionNumber); - if (actionNumberNode != null) - { - actionNumberNode.InnerText = sequenceNumber.ToString(); - sequenceNumber++; - } + actionItem.SelectSingleNode(Constants.ActionNumber).InnerText = sequenceNumber.ToString(); + sequenceNumber++; } - // Clear existing children and append sorted action items - actionItemNode.RemoveAll(); + //Append sorted action items foreach (XmlNode actionItem in sortedActionItems) { actionItemNode.AppendChild(actionItem); diff --git a/src/UKHO.ERPFacade.API/Program.cs b/src/UKHO.ERPFacade.API/Program.cs index f7882407..e482cf72 100644 --- a/src/UKHO.ERPFacade.API/Program.cs +++ b/src/UKHO.ERPFacade.API/Program.cs @@ -25,6 +25,7 @@ using UKHO.ERPFacade.Common.Providers; using UKHO.ERPFacade.Common.PermitDecryption; using UKHO.Logging.EventHubLogProvider; +using UKHO.ERPFacade.API.Services; namespace UKHO.ERPFacade { @@ -164,6 +165,7 @@ void ConfigAdditionalValuesProvider(IDictionary additionalValues sapActionConfiguration = configuration.GetSection("SapActionConfiguration").Get()!; builder.Services.Configure(configuration.GetSection("EESHealthCheckEnvironmentConfiguration")); builder.Services.Configure(configuration.GetSection("PermitConfiguration")); + builder.Services.Configure(configuration.GetSection("AioConfiguration")); builder.Services.AddSingleton(); @@ -178,6 +180,7 @@ void ConfigAdditionalValuesProvider(IDictionary additionalValues builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); ConfigureHealthChecks(builder); diff --git a/src/UKHO.ERPFacade.API/Services/IS57Service.cs b/src/UKHO.ERPFacade.API/Services/IS57Service.cs new file mode 100644 index 00000000..bafd564a --- /dev/null +++ b/src/UKHO.ERPFacade.API/Services/IS57Service.cs @@ -0,0 +1,9 @@ +using Newtonsoft.Json.Linq; + +namespace UKHO.ERPFacade.API.Services +{ + public interface IS57Service + { + Task ProcessS57Event(JObject encEventJson); + } +} diff --git a/src/UKHO.ERPFacade.API/Services/S57Service.cs b/src/UKHO.ERPFacade.API/Services/S57Service.cs new file mode 100644 index 00000000..c92c3110 --- /dev/null +++ b/src/UKHO.ERPFacade.API/Services/S57Service.cs @@ -0,0 +1,99 @@ +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using UKHO.ERPFacade.API.Helpers; +using UKHO.ERPFacade.Common.Configuration; +using UKHO.ERPFacade.Common.Constants; +using UKHO.ERPFacade.Common.Exceptions; +using UKHO.ERPFacade.Common.HttpClients; +using UKHO.ERPFacade.Common.IO; +using UKHO.ERPFacade.Common.IO.Azure; +using UKHO.ERPFacade.Common.Logging; +using UKHO.ERPFacade.Common.Models; +using UKHO.ERPFacade.Common.Models.TableEntities; + +namespace UKHO.ERPFacade.API.Services +{ + public class S57Service : IS57Service + { + private readonly ILogger _logger; + private readonly IAzureTableReaderWriter _azureTableReaderWriter; + private readonly IAzureBlobEventWriter _azureBlobEventWriter; + private readonly IAzureQueueHelper _azureQueueHelper; + private readonly ISapClient _sapClient; + private readonly IEncContentSapMessageBuilder _encContentSapMessageBuilder; + private readonly IOptions _sapConfig; + private readonly IOptions _aioConfig; + private List _aioCells = []; + + public S57Service(ILogger logger, + IAzureTableReaderWriter azureTableReaderWriter, + IAzureBlobEventWriter azureBlobEventWriter, + IAzureQueueHelper azureQueueHelper, + ISapClient sapClient, + IEncContentSapMessageBuilder encContentSapMessageBuilder, + IOptions sapConfig, + IOptions aioConfig) + { + _logger = logger; + _azureTableReaderWriter = azureTableReaderWriter; + _azureBlobEventWriter = azureBlobEventWriter; + _azureQueueHelper = azureQueueHelper; + _sapClient = sapClient; + _encContentSapMessageBuilder = encContentSapMessageBuilder; + _sapConfig = sapConfig ?? throw new ArgumentNullException(nameof(sapConfig)); + _aioConfig = aioConfig; + + _aioCells = !string.IsNullOrEmpty(_aioConfig.Value.AioCells) ? new(_aioConfig.Value.AioCells.Split(',').Select(s => s.Trim())) : + throw new ERPFacadeException(EventIds.AioConfigurationNotFoundException.ToEventId(), "Aio cell configuration not found."); + } + + public async Task ProcessS57Event(JObject encEventJson) + { + var eventData = JsonConvert.DeserializeObject(encEventJson.ToString()); + + if (IsAioCell(eventData.Data.Products.Select(x => x.ProductName).ToList())) + { + _logger.LogInformation(EventIds.NoProcessingOfNewEncContentPublishedEventForAioCells.ToEventId(), "The enccontentpublished event will not be processed for Aio cells."); + return; + } + + EncEventEntity encEventEntity = new() + { + RowKey = Guid.NewGuid().ToString(), + PartitionKey = Guid.NewGuid().ToString(), + Timestamp = DateTime.UtcNow, + CorrelationId = eventData.Data.CorrelationId, + RequestDateTime = null + }; + + _logger.LogInformation(EventIds.AddingEntryForEncContentPublishedEventInAzureTable.ToEventId(), "Adding/Updating entry for enccontentpublished event in azure table."); + await _azureTableReaderWriter.UpsertEntity(eventData.Data.CorrelationId, Constants.S57EventTableName, encEventEntity); + + _logger.LogInformation(EventIds.UploadEncContentPublishedEventInAzureBlobStarted.ToEventId(), "Uploading enccontentpublished event payload in blob storage."); + await _azureBlobEventWriter.UploadEvent(encEventJson.ToString(), Constants.S57EventContainerName, eventData.Data.CorrelationId + '/' + Constants.S57EncEventFileName); + _logger.LogInformation(EventIds.UploadEncContentPublishedEventInAzureBlobCompleted.ToEventId(), "The enccontentpublished event payload is uploaded in blob storage successfully."); + + var sapPayload = _encContentSapMessageBuilder.BuildSapMessageXml(JsonConvert.DeserializeObject(encEventJson.ToString())); + + _logger.LogInformation(EventIds.UploadSapXmlPayloadInAzureBlobStarted.ToEventId(), "Uploading the SAP XML payload in blob storage."); + await _azureBlobEventWriter.UploadEvent(sapPayload.ToIndentedString(), Constants.S57EventContainerName, eventData.Data.CorrelationId + '/' + Constants.SapXmlPayloadFileName); + _logger.LogInformation(EventIds.UploadSapXmlPayloadInAzureBlobCompleted.ToEventId(), "SAP XML payload is uploaded in blob storage successfully."); + + var response = await _sapClient.PostEventData(sapPayload, _sapConfig.Value.SapEndpointForEncEvent, _sapConfig.Value.SapServiceOperationForEncEvent, _sapConfig.Value.SapUsernameForEncEvent, _sapConfig.Value.SapPasswordForEncEvent); + + if (!response.IsSuccessStatusCode) + { + throw new ERPFacadeException(EventIds.RequestToSapFailed.ToEventId(), $"An error occurred while sending a request to SAP. | {response.StatusCode}"); + } + _logger.LogInformation(EventIds.EncUpdateSentToSap.ToEventId(), "ENC update has been sent to SAP successfully"); + + await _azureTableReaderWriter.UpdateEntity(eventData.Data.CorrelationId, Constants.S57EventTableName, new[] { new KeyValuePair("RequestDateTime", DateTime.UtcNow) }); + } + + private bool IsAioCell(IEnumerable products) + { + return products.Any(_aioCells.Contains); + } + } +} diff --git a/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj b/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj index 9afae35f..37f6256c 100644 --- a/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj +++ b/src/UKHO.ERPFacade.API/UKHO.ERPFacade.API.csproj @@ -15,12 +15,6 @@ 8600;8602;8604;8618;8625 - - - - - - diff --git a/src/UKHO.ERPFacade.API/appsettings.json b/src/UKHO.ERPFacade.API/appsettings.json index a308ce60..c624b00a 100644 --- a/src/UKHO.ERPFacade.API/appsettings.json +++ b/src/UKHO.ERPFacade.API/appsettings.json @@ -61,5 +61,8 @@ }, "PermitConfiguration": { "PermitDecryptionHardwareId": "" + }, + "AioConfiguration": { + "AioCells": "" } } diff --git a/src/UKHO.ERPFacade.Common/Configuration/AioConfiguration.cs b/src/UKHO.ERPFacade.Common/Configuration/AioConfiguration.cs new file mode 100644 index 00000000..1d0f8c7f --- /dev/null +++ b/src/UKHO.ERPFacade.Common/Configuration/AioConfiguration.cs @@ -0,0 +1,10 @@ +using System.Diagnostics.CodeAnalysis; + +namespace UKHO.ERPFacade.Common.Configuration +{ + [ExcludeFromCodeCoverage] + public class AioConfiguration + { + public string AioCells { get; set; } + } +} diff --git a/src/UKHO.ERPFacade.Common/Constants/Constants.cs b/src/UKHO.ERPFacade.Common/Constants/Constants.cs index 74978679..24963e27 100644 --- a/src/UKHO.ERPFacade.Common/Constants/Constants.cs +++ b/src/UKHO.ERPFacade.Common/Constants/Constants.cs @@ -86,7 +86,8 @@ public static class Constants public const int MaxXmlNodeLength = 250; public const int MaxAgencyXmlNodeLength = 2; - + public const string UkhoWeekNoFormat = "D2"; + public const string UkhoWeekNoFormatSeparator = ""; //RecordOfSale xml payload builder public const string RecordOfSaleSapXmlTemplatePath = "SapXmlTemplates\\SAPRoSRequest.xml"; @@ -138,6 +139,7 @@ public static class Constants public const string ChangeEncCellAction = "CHANGE ENC CELL"; public const string PermitWithSameKey = "PermitWithSameKey"; public const string PermitWithDifferentKey = "PermitWithDifferentKey"; + public const string AioKey = "AIO"; //LicenseUpdate xml payload nodes public const string LicTransaction = "CHANGELICENCE"; diff --git a/src/UKHO.ERPFacade.Common/Logging/EventIds.cs b/src/UKHO.ERPFacade.Common/Logging/EventIds.cs index f8d82346..93c87a27 100644 --- a/src/UKHO.ERPFacade.Common/Logging/EventIds.cs +++ b/src/UKHO.ERPFacade.Common/Logging/EventIds.cs @@ -446,7 +446,17 @@ public enum EventIds /// /// 940088 - Permit string provided empty in json payload. /// - EmptyPermitStringException = 940088 + EmptyPermitStringException = 940088, + + /// + /// 940087 - Aio configuration is not found. + /// + AioConfigurationNotFoundException = 940089, + + /// + /// 940088 - The enccontentpublished event will not be processed for Aio cells. + /// + NoProcessingOfNewEncContentPublishedEventForAioCells = 940090 } /// diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadePayloadTestData/AIONewCell.JSON b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadePayloadTestData/AIONewCell.JSON new file mode 100644 index 00000000..729b19dd --- /dev/null +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadePayloadTestData/AIONewCell.JSON @@ -0,0 +1,2897 @@ +{ + "specversion": "1.0", + "type": "uk.gov.ukho.encpublishing.enccontentpublished.v2.2", + "source": "https://encpublishing.ukho.gov.uk", + "id": "47c82948-f389-41bb-a77c-bdd3f8c306d7", + "time": "2024-10-11T12:54:30.6083284+00:00", + "subject": "GB800001", + "datacontenttype": "application/json", + "data": { + "correlationId": "19cc417e-c2a1-438d-2837-08dce9f35151", + "ukhoWeekNumber": { + "year": 2024, + "week": 28, + "currentWeekAlphaCorrection": false + }, + "products": [ + { + "dataSetName": "GB800001.000", + "productName": "GB800001", + "title": "Admiralty Information Overlay", + "scale": 1, + "usageBand": 8, + "editionNumber": 32, + "updateNumber": 0, + "mayAffectHoldings": true, + "contentChange": true, + "permit": "ThisWillBeReplacedWithActualPermitFromKeyvault", + "providerCode": "11", + "providerName": "VAR Unique", + "size": "large", + "bundle": [ + { + "bundleType": "DVD", + "location": "M1;B3" + } + ], + "status": { + "statusName": "New Edition", + "statusDate": "2024-01-11", + "isNewCell": true + }, + "replaces": [], + "replacedBy": [], + "additionalCoverage": [], + "geographicLimit": { + "boundingBox": { + "northLimit": 90, + "southLimit": -90, + "eastLimit": -180, + "westLimit": 180 + } + }, + "inUnitsOfSale": [], + "s63": { + "name": "GB800001.000", + "hash": "3F1F37386541599066AFDA9967A8555730661B7DE9E0B269DBEEDAD240111DBE", + "fileSize": 1998768, + "compression": true, + "s57Crc": "DB4A0A77" + }, + "signature": { + "name": "GBP00001.000", + "hash": "9FB68AA72D3D6138E1DF2DB2FC8946783655942B9D6E7143C11F46A58848BC50", + "fileSize": 874 + }, + "ancillaryFiles": [ + { + "name": "GBNOOVER.TXT", + "hash": "44460F8B9586E7D5FD838F758BD7247B568706B4704E6BFC48217EB454049378", + "fileSize": 317 + }, + { + "name": "GB196063.TXT", + "hash": "36142A45A992CC023C64D444F161639C89CF37009582AED2C74D1C08C4B2F85A", + "fileSize": 719 + }, + { + "name": "GB224295.TXT", + "hash": "36528855E0E1484F8DCC211F2BCA369D93F4433C7380C9F91C616E283E43F73C", + "fileSize": 629 + }, + { + "name": "GB238002.TIF", + "hash": "1C7B04F6D39CA1AD0E7B9CDAF4BAC0F16C4BC5B7014C7262F9D4A2BC64666A84", + "fileSize": 46260 + }, + { + "name": "GB247A0T.TIF", + "hash": "235410C7928C9B459BB570FD131DF98162AF11DA0E1C125CCF9469A40E27BA82", + "fileSize": 315938 + }, + { + "name": "GB195627.TXT", + "hash": "6F508529D437A93E4141F87A2577339212EF4E7DD2667B67B718AD0D0123401C", + "fileSize": 1827 + }, + { + "name": "GB224297.TXT", + "hash": "88A93130131692572C9C36F3175E9B12B59FACB6E2D724943287C2403546C7A0", + "fileSize": 738 + }, + { + "name": "GB196384.TXT", + "hash": "CF4E54645EE318CC385C8A6B739CB9A257CF1856CCDB20D212D87A2C96094DEE", + "fileSize": 2775 + }, + { + "name": "GB03180X.TIF", + "hash": "BACA4A9F9326CC88FD2DE5BFEABF41704E73D95B75C7175A1EDF5757900A89E4", + "fileSize": 22988 + }, + { + "name": "GB419516.TXT", + "hash": "DAA23DADF320280FD370200DA12353765ACE02C6075618BB7AB366DF68B61C72", + "fileSize": 6616 + }, + { + "name": "GB419516.TIF", + "hash": "3C30D2A28AECEEF3133DCDFD1C08E30136249A40EF883B525B2987A3388F01C2", + "fileSize": 143924 + }, + { + "name": "GB224182.TXT", + "hash": "13EC9D5C61D491354B3EC46239E2FF49E238852F9E074920A364991DAD8155C1", + "fileSize": 2178 + }, + { + "name": "GB224224.TXT", + "hash": "4D95F4F810AC227F01F6377C5E79521E10B24AF2472FF05B9C99BBB2FE2A7331", + "fileSize": 561 + }, + { + "name": "GB282F01.TIF", + "hash": "9FF65FA25F010BF766BF35B5D818CA86FFC8BE7B9A326F71953B159EEB3B6251", + "fileSize": 176454 + }, + { + "name": "GB224213.TXT", + "hash": "610F452C5826F55E36013E065C16F661CE3CCD3B4E7BC9753ACEF903BEF7B91B", + "fileSize": 756 + }, + { + "name": "GB1A480A.TIF", + "hash": "A6329F77CA136C47359D87A516EB5D48ECD993BC69246BF582904BF1BB20855D", + "fileSize": 21654 + }, + { + "name": "GB0C2009.TIF", + "hash": "A46CAD0AAF79E798992841B89F61FEF48046E6C781760D1D23E352A91E0F90B1", + "fileSize": 57800 + }, + { + "name": "GB224283.TXT", + "hash": "713C797415D37114455823DF19A8E9CEDA2814F06DB24001EE8FDC29E071A7FE", + "fileSize": 1023 + }, + { + "name": "GB0EF00Q.TIF", + "hash": "AAEE690A8B2C55926FACB6A9FEC00599E582D02C02AD0653C2119E4C3B60102D", + "fileSize": 31056 + }, + { + "name": "GB0C7518.TIF", + "hash": "E1B4155B5AF42731982522D22697DF05E4599E27F6672C073C86CE4B42646E44", + "fileSize": 56544 + }, + { + "name": "GB02882C.TIF", + "hash": "1978E340A5AB486DEC29755BF31C3E13FC1F51DF02176CC30E2C28EA5FF1CF41", + "fileSize": 39312 + }, + { + "name": "GB211504.TIF", + "hash": "8015E3E3A4CEA81B770739CB78C65295055CDD223614D6CC3DB082B49FDC4653", + "fileSize": 34472 + }, + { + "name": "GB220598.TXT", + "hash": "40779EB122BC7CC06457D9042C6F62D29242546FF01076EE2E7DE03183A216D9", + "fileSize": 476 + }, + { + "name": "GB238001.TIF", + "hash": "DED60C443295F7F786E8185BC703BA19BB30DBFAEE24FDA5DB344A743DB488EC", + "fileSize": 46510 + }, + { + "name": "GB195385.TXT", + "hash": "1FB3853E000361AF1E56EC46B5A4D7B2EB754B3A721CAA2D59B1EB9C4027EB22", + "fileSize": 537 + }, + { + "name": "GB224530.TXT", + "hash": "037E36B2346A010407916C94C0A69508AC5E22C221CCA69F5827C6311716F0FB", + "fileSize": 1005 + }, + { + "name": "GB185983.TXT", + "hash": "677C028B08AF6A716ADB93BF27D2CAE1AAD75CD8D6AE0F28194743104261D4D7", + "fileSize": 506 + }, + { + "name": "GB172152.TXT", + "hash": "E446EF42E4D0EC4FEB3D45D3976FABB386895EEBCA8A29EC3EBF666F95266723", + "fileSize": 524 + }, + { + "name": "GB224798.TXT", + "hash": "BFD051AB7C02D919A5D2EFF1C3C24CA57363A396AED68FF16652A5B2B1BC2FC1", + "fileSize": 1339 + }, + { + "name": "GB195223.TXT", + "hash": "FCFA80FB3799FC26FA6374322C3CEA906EC055EDF31A7AF23E302B9935770C5A", + "fileSize": 511 + }, + { + "name": "GB466616.TXT", + "hash": "2C2A18D3C73E858E323046B5A31CB57A4652F6E23192BB64ACC554C03FB35BF0", + "fileSize": 817 + }, + { + "name": "GB221105.TXT", + "hash": "2B65853F6746B8F367DAF9D8D75601BA4616B8B6D8E946F8662E05024180F1F3", + "fileSize": 3533 + }, + { + "name": "GB0C200G.TIF", + "hash": "25F781876C12771115809973F21D01EDF8E08DDD496E39901086F6E550660B28", + "fileSize": 63400 + }, + { + "name": "GB211375.TXT", + "hash": "B0A454DCF5151B86F9A4B00CBDCF1C37E25BE43AF61862BA8FCF6356EBE4451C", + "fileSize": 1004 + }, + { + "name": "GB194737.TXT", + "hash": "570A9E7E232F6C9CD6A0EBFE5334715C7D4342D1B1CE2E43C70AA7FFAD5D7B5C", + "fileSize": 640 + }, + { + "name": "GB449216.TXT", + "hash": "9161023B78D21DD67238DD8DA708454475DD317E2D37715F7EAA71EA4DBA329B", + "fileSize": 5495 + }, + { + "name": "GB224923.TXT", + "hash": "C39DFB7EBC96C48D0EC9B610D5FF7935ADC0EE3D0E74A3A7A09AD7B8A27E4C6B", + "fileSize": 559 + }, + { + "name": "GB284401.TIF", + "hash": "F7CE3DDADA4684066F53C9C516436C2DFDA2FEED763935B048F65819196973E5", + "fileSize": 121474 + }, + { + "name": "GB211320.TXT", + "hash": "8E77FD533F8A6443B08FC2C06DB598B8F1EBC53DCCDF15CA2E7C8A42B82BBF27", + "fileSize": 507 + }, + { + "name": "GB212825.TXT", + "hash": "097CA5387245CDA596B854D9612F6DCCBC1293A5C90003F41DA9A9169F1C51B3", + "fileSize": 804 + }, + { + "name": "GB260301.TIF", + "hash": "8190B904C4C4557AA03F5E14DDA22251A50EFF5C95C4DFF13005C40B55BB508A", + "fileSize": 609688 + }, + { + "name": "GB0C7515.TIF", + "hash": "2686F25B26581BCC39001C55C3C71A9F26D4907B5B964361D09B76E2D523FC53", + "fileSize": 56684 + }, + { + "name": "GB211276.TXT", + "hash": "7DF73D5728A3D705868B58966D20DA94A7531703BC96E85BC754097B4DDCB4FD", + "fileSize": 674 + }, + { + "name": "GB194697.TXT", + "hash": "D9416704907480019275260B776D60642B4390137BF0F8C2DE8BD5515F1C40B6", + "fileSize": 698 + }, + { + "name": "GB210874.TXT", + "hash": "C2545B1C9A23099A341CCE6E6F4DEF2A5CE3D5BE2BCDD57A77CF2B25A379FACC", + "fileSize": 2960 + }, + { + "name": "GB210874.TIF", + "hash": "5BBA9B49BAD708D8942E2B8B6AB0D2B4E3543A7248F3765734D06DF7102BD41C", + "fileSize": 120764 + }, + { + "name": "GB194326.TXT", + "hash": "C94CD837183F862E62DA902AD691C8A439F7317C0DDE5017A6BB51EC3E8A4FA3", + "fileSize": 858 + }, + { + "name": "GB136C02.TIF", + "hash": "0B770A5E3E0C2559DEDAE0CF144F6B6533E9E9AF5DF7D17EF4AA02A8C8CA758E", + "fileSize": 70144 + }, + { + "name": "GB194290.TXT", + "hash": "C7B140D956B5586AC2C76BAA262C92ED97BDC100E2FE1A81EE187A1005BC20D7", + "fileSize": 539 + }, + { + "name": "GB26011D.TIF", + "hash": "D2B5BE5D00C440B2EC3A6F983FC99F7F1024BA35DEB3D02BD41849B60DE2F2A2", + "fileSize": 91616 + }, + { + "name": "GB175395.TXT", + "hash": "31920C9365CEC76855DDFB5AA998F9BF7A8702DF1AC3E26695AF65F0F081121D", + "fileSize": 543 + }, + { + "name": "GB193987.TXT", + "hash": "B35F72E24ED24C6611F7B6081823B44F6F1D503D44BE6BD938714A6EF6807485", + "fileSize": 850 + }, + { + "name": "GB0DA703.TIF", + "hash": "3F4BE464968CF197B6E9D810A4AF8536F88312ACAA1162BF09DC95F4C932213A", + "fileSize": 35624 + }, + { + "name": "GB0C2001.TIF", + "hash": "22AFF6CDB47B176E8B7205A12B00BF8D38730B2B31A7E051AE58562BC89FA0F4", + "fileSize": 59384 + }, + { + "name": "GB210706.TXT", + "hash": "24DB9B341BD9E26C3DB5ABC0E19964597DCCE3898A7E2C4B081A3A472EDBB44E", + "fileSize": 739 + }, + { + "name": "GB193109.TXT", + "hash": "2E2B8DC2BE69CCE785795C79D16E3AF95CD1A2C94801D2FE5D4BD37A7BB23D62", + "fileSize": 469 + }, + { + "name": "GB156C12.TIF", + "hash": "3D6956259025C78C3DE970B9BF99FF9451F8E0992EFB7A0E78D9DBD3DFBE486D", + "fileSize": 52876 + }, + { + "name": "GB0BE706.TIF", + "hash": "290643934D74CDF153807A85DA38D204520BDD68AFAC9055BB22DE3CCC0092DB", + "fileSize": 30732 + }, + { + "name": "GB193392.TXT", + "hash": "15911D77984536BB7A2F27F834C480532D71FD17E13DBD33EDE3140B0048B700", + "fileSize": 552 + }, + { + "name": "GB193088.TXT", + "hash": "E4069AB3970151FEAD09B3C7B0BA1DD7BAD7EAF1D806BD6482100B29DB23CD83", + "fileSize": 487 + }, + { + "name": "GB210165.TXT", + "hash": "AE54AAF8E47E149E8111E6659B9813029E0B0D3C0B593503DDD2FAEE36CBF83D", + "fileSize": 508 + }, + { + "name": "GB192871.TXT", + "hash": "DFA5FE168A3A0D71E6D939C62BF08363E3F9D086DB9DAE872176A15FC96AABFA", + "fileSize": 728 + }, + { + "name": "GB210219.TXT", + "hash": "30070A3336FCA532DFC29A6EBB7FB51EA98A89EBE1E73B9D34CE7478BC55B7F3", + "fileSize": 504 + }, + { + "name": "GB192745.TXT", + "hash": "A50D6AE1E0E5419BFEA93785B5C4A1377B648018BAE0E903B91F571628AD7033", + "fileSize": 1398 + }, + { + "name": "GB0B390F.TIF", + "hash": "903F585B1FA1432F15C048804FB622CD57ED43F9B9DB776170050C59706E0E13", + "fileSize": 29648 + }, + { + "name": "GB0C1F09.TIF", + "hash": "EFEC2012A3F5C8094FB67661D2DE804CA7E26B0F80E56836CA22AE262DF43B18", + "fileSize": 22580 + }, + { + "name": "GB206251.TXT", + "hash": "EE8840E31FC4EA3CA42A952273000C1B22652DA0FF88F810CA9524AB178DDD22", + "fileSize": 563 + }, + { + "name": "GB192630.TXT", + "hash": "2F8ADBD1D96AE48391F4574DA0D6B1A2CB5880030862F3398E804FC5D40586D0", + "fileSize": 513 + }, + { + "name": "GB194195.TXT", + "hash": "B284259BD220CD9D46270F7B63582B58626088C597A34A766D96039B53CEA492", + "fileSize": 899 + }, + { + "name": "GB192345.TXT", + "hash": "37C51FE3D285708156DD8D0D4B42931574D4575B112001568700D1F2DE4C91F2", + "fileSize": 679 + }, + { + "name": "GB123C0Z.TIF", + "hash": "8B3EFEC86E343A5FB2237074D71DA893EE380A001365CA3FF50E1BB5FF5BD9BE", + "fileSize": 162428 + }, + { + "name": "GB182839.TXT", + "hash": "A8618BEB0EFB865F2AB0AE0FF68D7C7C42C595B50FF9A322D219AB492E66C05D", + "fileSize": 2034 + }, + { + "name": "GB192203.TXT", + "hash": "29527C2EFEBAD27FDED12FCCCBFDDE307D02058888F893AF83F4C6AAB34CAA07", + "fileSize": 827 + }, + { + "name": "GB215164.TXT", + "hash": "19C81AD8935EA11D6E3A480D5F52F67FE04A8617F288EEF2581F7D5908F6A4CB", + "fileSize": 742 + }, + { + "name": "GB192106.TXT", + "hash": "86A8F37E723802C5062DC8CA59BCC8F43810E365727B40480855DB4F9F75CD5B", + "fileSize": 1036 + }, + { + "name": "GB211502.TIF", + "hash": "2828B4E83A8E1BECBCB5CABF7E9AEE4E89D9E2F7B9099D4DAF53EC0AB0E04E7B", + "fileSize": 12558 + }, + { + "name": "GB10080K.TIF", + "hash": "EB528642D46885128B3BF04E3BED4B591573C4CEEC2ABFCD9B287B83E18F990B", + "fileSize": 22272 + }, + { + "name": "GB204813.TXT", + "hash": "07F3043BB545425A1DE969D1ED44AFC08318E1B5D50BCAAEB54853360FCB6FAF", + "fileSize": 663 + }, + { + "name": "GB192078.TXT", + "hash": "44E88764DD59BD88C3492C2676A502929DCDD6871F51DFB58D4344AF6AD8E521", + "fileSize": 853 + }, + { + "name": "GB0C830Q.TIF", + "hash": "CA412735FFD9FFE075D946B194D1DFE408F2BF18A1A541F5822A655CAB981D3E", + "fileSize": 31580 + }, + { + "name": "GB204424.TXT", + "hash": "FAB05FDE6FCDFE7CB5BF686DB370AE440D6965B1A86931122F21E0EBDCD5937B", + "fileSize": 524 + }, + { + "name": "GB191646.TXT", + "hash": "A24B577E3194D66B9545C2D75ACB7A26A7C1E44DA83A07DBF6B3538CB3514D54", + "fileSize": 616 + }, + { + "name": "GB0BAB1V.TIF", + "hash": "DB2612405195B6989F633772C654BF95EED308375501F7641332280676A747F2", + "fileSize": 64948 + }, + { + "name": "GB123C0Y.TIF", + "hash": "21FEF325E6B75F3716EF9D02F1322FE561AAA25C3612D5DBD5511AD3724934A1", + "fileSize": 146568 + }, + { + "name": "GB204110.TXT", + "hash": "C2A6453D184364ECC502687DB8E10A8777844DCC14AB5C8D828737922A50CD4B", + "fileSize": 696 + }, + { + "name": "GB185625.TXT", + "hash": "975D38198A8F16A5559A46CEEAD93596EE7EEFD664D7BD596E302D52A5AC2140", + "fileSize": 692 + }, + { + "name": "GB0BAB1W.TIF", + "hash": "A51578EBF8FC2C24A9BA46743F0E40CEFF1FCB1173FDCD5D82317C8BDC43CF3F", + "fileSize": 49408 + }, + { + "name": "GB0C1F08.TIF", + "hash": "FAD0BB2AB894B8438804B4B45477D7F448431F96FF22E83BBFC71D517F65CCF2", + "fileSize": 29292 + }, + { + "name": "GB118606.TIF", + "hash": "AA7573263924DDC6C9691E8A88A9C8FDAAAEE0B202B26202D882673A754F544B", + "fileSize": 31328 + }, + { + "name": "GB118607.TIF", + "hash": "99A95DF3D953926FFFB6CFF25580E0F46F283B340F8F34D8FD624A70600BC018", + "fileSize": 37040 + }, + { + "name": "GB0C030D.TIF", + "hash": "B33BF36767DC0FE7536B0F6AA4A206F63255D5F8389105A48060F96F0A817FE2", + "fileSize": 65200 + }, + { + "name": "GB26233Q.TIF", + "hash": "72BED8CC6FAA9F56D56C0246D1401EC8A75ED48045AC4E5EB9B1E7FCB6FF6846", + "fileSize": 258114 + }, + { + "name": "GB034E1K.TIF", + "hash": "928549E90A8F90553BC8F29591FAB6286AF5F3693FA73F6063D0968A8B50A6FB", + "fileSize": 115204 + }, + { + "name": "GB287D03.TIF", + "hash": "E2D910D43C00716C6E37169061BB5899509FA3D512B87D250A33A7B9E5C6FF85", + "fileSize": 76526 + }, + { + "name": "GB1DF41D.TIF", + "hash": "78DD5673729076FF5D6C016A43C7F0C6F8D3C92CC0953933A1876E4C214A89A8", + "fileSize": 58556 + }, + { + "name": "GB0C1F0B.TIF", + "hash": "5558A36FD9883BB951F74E22A9B6B6A7B0E7B274195DDE9EE591F7865FD44FA3", + "fileSize": 31812 + }, + { + "name": "GB26233R.TIF", + "hash": "AF73778BA424E1804DB16BF6FF245D05A63BA79F14C39034F8458214B365890F", + "fileSize": 181972 + }, + { + "name": "GB287D04.TIF", + "hash": "42E428F8FC6EF338A374857C308A0DAC25B4D91093F73DA50426D5ABE75EAB08", + "fileSize": 50678 + }, + { + "name": "GB26233S.TIF", + "hash": "4E7A7A27C11A171B91BA087048FF78455621A74B68BC5B678315652E0C659D7B", + "fileSize": 184214 + }, + { + "name": "GB0BF109.TIF", + "hash": "AB0B0C24058DA318DB701C76664A97783061E9C5ABE948AD069A83762701951A", + "fileSize": 14820 + }, + { + "name": "GB25F508.TIF", + "hash": "07C3214EB5493CB36C97F0EDC8A33BB7E68B8B2CBC57A7AE999AEA2A841B1AE6", + "fileSize": 108652 + }, + { + "name": "GB26233T.TIF", + "hash": "19CB6DECFD0F309947007CEC662B5B04124E4C01A214C242586956EEBA397D5C", + "fileSize": 269436 + }, + { + "name": "GB26233V.TIF", + "hash": "C74F2A8185F890DDDB3085687B8E9A40A5B3C27287DBD6D7004D938A3E012567", + "fileSize": 140768 + }, + { + "name": "GB10081E.TIF", + "hash": "DA74CD93F0D4385311F3CB88B9F8DDC689428511DF96BAF6616A560D8807794F", + "fileSize": 18244 + }, + { + "name": "GB0C1F0A.TIF", + "hash": "5A6320AC9EC52A8F34109BAC8BECA21B68E5240672379097997567D884F91E8D", + "fileSize": 37512 + }, + { + "name": "GB25F509.TIF", + "hash": "BEDC09DCBF901EE64437EBB8FB0983F39F160A1CFDB4F8417AB481C2B10110BC", + "fileSize": 168574 + }, + { + "name": "GB26233W.TIF", + "hash": "2F6A271C8223FC6262C728D7D86C99497A3F471B2849D8F7E2574F41EFCF21A6", + "fileSize": 372566 + }, + { + "name": "GB0C3119.TIF", + "hash": "833A7E459206C24273A50201E460CB3C1E42AF68BC6D017521DD51A8CD95F85B", + "fileSize": 27012 + }, + { + "name": "GB1DF41C.TIF", + "hash": "008108C458AC1C7A66B9B58F7C279D8A969A992884897363CC73845BA5AC0547", + "fileSize": 53996 + }, + { + "name": "GB1DF507.TIF", + "hash": "9D8F3870A08B4C877D5310A2ED225503B373D2DEC86153621D7D97601BC916EC", + "fileSize": 133104 + }, + { + "name": "GB100712.TIF", + "hash": "E6F851E87DEFBE0B0B964860C4218B08C84DE46D6A7BD0FA8C3F15D59277DE10", + "fileSize": 19288 + }, + { + "name": "GB25F206.TIF", + "hash": "EA39403C93A338584898763A85BDB3D6227EA1094A40312A1D2CD96F57B4A284", + "fileSize": 345908 + }, + { + "name": "GB123C0X.TIF", + "hash": "621BA29B6B38535A8A2B305F6E144B5D9D628F1F7B464E506908BF7A0F62D101", + "fileSize": 57512 + }, + { + "name": "GB0D930F.TIF", + "hash": "ED3F3F324D2962582862B7991B772C7B1EF99B8BB4732754D42A554EDA1B0C08", + "fileSize": 67104 + }, + { + "name": "GB25F207.TIF", + "hash": "BC45DE4B5437265B8F46D5963CB946443DC545E7FC6BA1F05F3346BAB77D959A", + "fileSize": 172170 + }, + { + "name": "GB262333.TIF", + "hash": "3A06A8C628445335BE5368235B9C23CFDE69DAA7F8E3279D597BF6B7E6632065", + "fileSize": 293788 + }, + { + "name": "GB25F208.TIF", + "hash": "9D8CFA6F4D1D0C72C5CB3EF2E3C1B197840596B6EA9855500305470224F3FE2F", + "fileSize": 149664 + }, + { + "name": "GB262334.TIF", + "hash": "805E66AB503A461017D44D3145424236F47A2E1AA3F2773A76F9A5E7107DCD01", + "fileSize": 88406 + }, + { + "name": "GB156C1T.TIF", + "hash": "FCF8AE6FA272378DD11439E4A56FF1CC3068C587B384AFE37DC5E10DE3B6EE5A", + "fileSize": 58416 + }, + { + "name": "GB196402.TXT", + "hash": "1B6F7E04BC69DECA08D22AA01BD23C199AE87797FDCD87CD1FC5BCEF3AC6D236", + "fileSize": 2056 + }, + { + "name": "GB218813.TXT", + "hash": "CCA408E3451D8DD13426C0CA6CBEC8B601FB0C27EA66AF6B9FB364C9EB499214", + "fileSize": 596 + }, + { + "name": "GB262336.TIF", + "hash": "CE79B9DBF7B46DAA8B9E3959AF8A01740D685C54447A68D7811FFF46F185D180", + "fileSize": 353252 + }, + { + "name": "GB1B6B03.TIF", + "hash": "3C949AE1E5005EB7102622412899AD3DA22F67CB48FDA6661784F6BE850B0F18", + "fileSize": 94968 + }, + { + "name": "GB087716.TXT", + "hash": "C25A3CD9D2F9D031908F179E06AF2CC255F9D7B6BE58A5F1E0E9B7DB7868F820", + "fileSize": 1020 + }, + { + "name": "GB645315.TXT", + "hash": "62DDA869B9E7D4C118203A3271ECF889558CCDD50B4E1E9F3C1489AD454C3BC4", + "fileSize": 606 + }, + { + "name": "GB1DF40B.TIF", + "hash": "918BD72EF79C803E416C1956245E122A631F08E2E2774AAD98BC13585DCA82B0", + "fileSize": 33752 + }, + { + "name": "GB092C05.TIF", + "hash": "4DF9B4327AE4546B7EC3F614B519F99BE3F123CEFD4A5AC917B69910650A2595", + "fileSize": 32464 + }, + { + "name": "GB028A0Y.TIF", + "hash": "65F2D4B59E6C9922A9CFEF96A3C158DB6B8BE9BF3EF771DD4E8E98333E9BEEF7", + "fileSize": 125712 + }, + { + "name": "GB214622.TXT", + "hash": "DE32D4E28DC898712ADA2230175EE8BEA11D36A60C9E86B3CF5A8BEFA81FA178", + "fileSize": 1188 + }, + { + "name": "GB214555.TXT", + "hash": "B9B8EFF9601721FA51163C4E4BE2897B47772C00B80B1118F73774607836F391", + "fileSize": 816 + }, + { + "name": "GB1B6B01.TIF", + "hash": "A84DE55EA587C267E0DC08C5B469AAB69C7B200BD9850A9771F54137FED20E45", + "fileSize": 67132 + }, + { + "name": "GB214529.TXT", + "hash": "38C06E4EC01684ABFEEFA4B331AC1B2675CD31FFBE119E5AAC8639C16D71452D", + "fileSize": 935 + }, + { + "name": "GB1DF402.TIF", + "hash": "56CCA4FA125B3DA869720C986EC2EEADE596B5E1A449266CD1AF3540E48CA99A", + "fileSize": 30084 + }, + { + "name": "GB18E107.TIF", + "hash": "A603DB4ADF1A95F0C6C89F5735398F1253627A590D7B22F2E4DC09F3F036F9AC", + "fileSize": 111264 + }, + { + "name": "GB0C830T.TIF", + "hash": "1A374846920DD6BD825870CB0FD0F6A1CE557C71BF6714D6825ED31513C1CFA8", + "fileSize": 40760 + }, + { + "name": "GB156C18.TIF", + "hash": "78C61A302A5E9C98D7077BB10AE560D8E1CFBB94B825B96BD317FE56CC8B2F43", + "fileSize": 50332 + }, + { + "name": "GB11BA0O.TIF", + "hash": "833F0EA80D4C52A036380BF88C0C5DB1FD853E03617EACBB205C98C2ABCEFFA8", + "fileSize": 16148 + }, + { + "name": "GB232504.TXT", + "hash": "AE3DE737DA5A1AF2FF84D3A0F7E252995B610A35E65D76212D784CC0E6506B7D", + "fileSize": 4687 + }, + { + "name": "GB1B9007.TIF", + "hash": "FCDE7361EA5114439994F45E5304AAAC876CC03A62EB49875BDCFC59C6DD0A2F", + "fileSize": 63076 + }, + { + "name": "GB10FE0W.TIF", + "hash": "7234515D4339F233796DA1D7CC09CEB33D6169D7E051A25827C642B4A4D5B9C8", + "fileSize": 35520 + }, + { + "name": "GB214125.TXT", + "hash": "86EB1FC4C5E93E05D456FDA7E9562CD4F7E29C4803875BD39194D62AD0F37930", + "fileSize": 850 + }, + { + "name": "GB034E2C.TIF", + "hash": "F7D2117667216DF65EC0BC982750409DCFDE9733522140D5A19BE22948C74582", + "fileSize": 191596 + }, + { + "name": "GB213931.TXT", + "hash": "E2096145E03622632CCCF733DA1DD1D38F61057D446A1A66E9EAAB512A1034D3", + "fileSize": 947 + }, + { + "name": "GB034E2D.TIF", + "hash": "547BCC5DDD0BB00A82530E3862577134BFE31A52F8C16E60529E7726466D47D8", + "fileSize": 19756 + }, + { + "name": "GB213859.TXT", + "hash": "189F28C86EB302CA11974C027239BA186752A939E727EF3B6C207C4C58A2B8AE", + "fileSize": 540 + }, + { + "name": "GB034E2E.TIF", + "hash": "12043D51FA21D8486435EEE07BD2C9650FA7945AD571EE60DFD7AD236AE44EA7", + "fileSize": 46722 + }, + { + "name": "GB213518.TXT", + "hash": "012D7D213DC8AB5084F72C60D91CC2BFD7C523402DE2DE70E30130A6C2B9519F", + "fileSize": 736 + }, + { + "name": "GB034E2F.TIF", + "hash": "42B9C4C0EADC195A778D28EE2A00C46DD7EC0B27F0CC2A0C4D05E01D9FF6F21F", + "fileSize": 23056 + }, + { + "name": "GB0CAD0G.TIF", + "hash": "E8696425B3D7F8F6029C5E5FE318F0596EC9D1FCA7175D3A6369054A272D1D63", + "fileSize": 19032 + }, + { + "name": "GB213513.TXT", + "hash": "AC24DE92FBEAF48A0A8971390D0A0A60BB2578B809764027533BB7C3D59251AA", + "fileSize": 789 + }, + { + "name": "GB0BE707.TIF", + "hash": "CDB3AFAFC12EEB4FBB8975C8D8FC77597E78FF483AB273E8659949184B6D08D6", + "fileSize": 19060 + }, + { + "name": "GB212409.TXT", + "hash": "2FC451CD5DC100DC7C55AC934BBF35E3E5333A17B97B68A6B89EF64EC2468FA3", + "fileSize": 1124 + }, + { + "name": "GB1B600C.TIF", + "hash": "6907714C27EAA9B2EFCF8EADCBE33861AF0978FB4FC16E7B67FF10526F0143B2", + "fileSize": 64696 + }, + { + "name": "GB0B392J.TIF", + "hash": "C0B71DF4CFFEAD269D457B1A8A34A8F1D9A96183DE3C4DB0FDCA8B0EB58D964D", + "fileSize": 18672 + }, + { + "name": "GB18330E.TIF", + "hash": "31AC9DB77282896D13C4726878822E6198CA1611BC95E26342F66B08F43992B1", + "fileSize": 164548 + }, + { + "name": "GB282E02.TIF", + "hash": "B71400AD1161C39DACF085A734FD5DF4782F44A668D312DA628CA56FB6004779", + "fileSize": 219584 + }, + { + "name": "GB232805.TXT", + "hash": "DB141D3BE92FCDEB7903188B997BF745E407BED55525DA6F7090A3EF70402EF3", + "fileSize": 566 + }, + { + "name": "GB1E2E09.TIF", + "hash": "7ED4FC70B2505D54CD624A634DE4BCEF0ABD60E35C89E48824A546B338510D28", + "fileSize": 18320 + }, + { + "name": "GB19060Q.TIF", + "hash": "9DF02435D552A957365544EFC29CA69C61926978BFD3ECF9EB1B2D6523A5F415", + "fileSize": 106236 + }, + { + "name": "GB050D05.TIF", + "hash": "B8757E86119BACCADDFE9EB5362A358EEFB631C028310A6B4A3AE6D8952A3593", + "fileSize": 23116 + }, + { + "name": "GB220474.TXT", + "hash": "808EB94C639D7A599BF012894CCCF68AD739B1BD982C2BB47684F699FE0D52D9", + "fileSize": 4016 + }, + { + "name": "GB232806.TXT", + "hash": "D3362AF3DF17B7D7768503D8FBFF31E7713C416BC89FD4B8FCCDC2E5489E6F5B", + "fileSize": 565 + }, + { + "name": "GB224962.TXT", + "hash": "202FAFD4259BC15ACA0DEAF68ACAEC7E4EE04EECAD56D58A802656137423EDDA", + "fileSize": 525 + }, + { + "name": "GB232837.TXT", + "hash": "478A85026143CB09B2AC6F1D47047D2BE6B22860E74D8E4B1CD243F773DE682F", + "fileSize": 1005 + }, + { + "name": "GB224993.TXT", + "hash": "95FFA76930DF189DEDFA4BBCE3CEC72C1E7190EE362A7FD5142F00805AD0C250", + "fileSize": 522 + }, + { + "name": "GB232821.TXT", + "hash": "3D1796A28BBC4AA813E4F598B1B9B96287B114D554549E48F5AFB912A83239A6", + "fileSize": 556 + }, + { + "name": "GB225134.TXT", + "hash": "99C73C33BAA20F42ACDFD4EC45A37BC9DFAFB37BA422297F899C49D8D4436220", + "fileSize": 527 + }, + { + "name": "GB232978.TXT", + "hash": "A225DD2244A2A91DFEC1177F311406816920FB87E234CD4E77B9CCE8D1F69168", + "fileSize": 957 + }, + { + "name": "GB230098.TXT", + "hash": "4461FE1279E2EF2C425F05C027F6F28AF01F52B0AA86D5253FFBFE3962DEED6B", + "fileSize": 586 + }, + { + "name": "GB231114.TXT", + "hash": "48EB724CEEF0FBB7167BFAADB6BD55F391EAD947FF42117EEF2889DEDF18720E", + "fileSize": 518 + }, + { + "name": "GB11B004.TIF", + "hash": "B60411963A7F87252A6B9A0EFCFB1274B25280B6C092FA135CF4EACB9A84EF5F", + "fileSize": 20664 + }, + { + "name": "GB230223.TXT", + "hash": "0B8AEA7ACE52402D36963C78A99D221ABE235E2D8FC143C69DD288826A9C88F9", + "fileSize": 705 + }, + { + "name": "GB232987.TXT", + "hash": "7F7E91188936EB524471A6038220CB625193104F2A80FB611383026D95CD1312", + "fileSize": 692 + }, + { + "name": "GB170D0B.TIF", + "hash": "5B878008405CF2D7C1D29C65AB5256279C02D3311B232B00F20A907A510DF840", + "fileSize": 51616 + }, + { + "name": "GB230244.TXT", + "hash": "64F85FC6513EF1F39397CD553B5446A3752665027F37074F22F2E9203245A6E6", + "fileSize": 1240 + }, + { + "name": "GB230397.TXT", + "hash": "E47F947D14C6E7F01100E08EDBA89E0B8AEE6DA87F184ECF3F7335E7CE03A231", + "fileSize": 2073 + }, + { + "name": "GB050D08.TIF", + "hash": "925C79780B5394C8DFB3F91C414FC4C1EFBD3D354E7E8C679F530907CA94E83D", + "fileSize": 24676 + }, + { + "name": "GB230607.TXT", + "hash": "7E2CEEBA36576C85843DC483B32F78451A5CD51D0DA71769C062EF6F697C46F7", + "fileSize": 492 + }, + { + "name": "GB178D06.TIF", + "hash": "FF1C7A1173DB91169E73B6C38E6F8207BBB05CA0037B3AD33E92FB7575206223", + "fileSize": 53584 + }, + { + "name": "GB230638.TXT", + "hash": "7E8831A334761CC45BFAC5CA3D6ECADA358EAAE089109CD361C955D589D9044A", + "fileSize": 1759 + }, + { + "name": "GB230686.TXT", + "hash": "789E7B3D0355D7657FD0CDE54F448FF1C145B48614F64DC22636A700A9D26043", + "fileSize": 572 + }, + { + "name": "GB230755.TXT", + "hash": "4E513F3F724CC72BA45F123FB834901DB284E090FEEA037E0B7F4CC255B46CC6", + "fileSize": 646 + }, + { + "name": "GB034E0Y.TIF", + "hash": "C30A020EF8B7FB16ECE954FB388071C280BCB1E948A08B0B02EE87F2146C8D3A", + "fileSize": 19452 + }, + { + "name": "GB230812.TXT", + "hash": "870E1FF1DB2D28CD2EA2F708D255648767FB9B51269B8DA2C956D7FC08455756", + "fileSize": 972 + }, + { + "name": "GB230810.TXT", + "hash": "334E7AAB63F81DC00B89B72059F54F4342405D285DC3978AC60975BB251BB844", + "fileSize": 2483 + }, + { + "name": "GB230810.TIF", + "hash": "8AD1D33C3C17640394FCE871191A63CF4A05EC2F38040ABBE07CEC67CD3C1FAE", + "fileSize": 150740 + }, + { + "name": "GB1DF40D.TIF", + "hash": "0857878352302A6E8B0DFDDB746989F5A6B9BBEF933245CF328A96EC09A6D8EF", + "fileSize": 47980 + }, + { + "name": "GB123E15.TIF", + "hash": "C524119F5EBC95EF82A22318BB7D18E251C396596685F311ACDC7443147374C2", + "fileSize": 327966 + }, + { + "name": "GB04710C.TIF", + "hash": "242290E7D0C66882B81CA8ECC0A05B24F78EC9938647B916F95CBD1E6559C61D", + "fileSize": 41164 + }, + { + "name": "GB230840.TXT", + "hash": "28D2B517F1F210DC0C868FF0F191DD542C704471DC20E49EEA3AB161E40CB56A", + "fileSize": 489 + }, + { + "name": "GB18EC16.TIF", + "hash": "D2A54A3DD4077752FD3BF40A4FF46C5109605FADF1C9954273968EFECB8A6208", + "fileSize": 133884 + }, + { + "name": "GB171397.TXT", + "hash": "7B73B683E95276516DAC6D13BAD39E173AD431FA5FD55103D45F6299C48671E2", + "fileSize": 931 + }, + { + "name": "GB203883.TXT", + "hash": "CE062D6D13B57FBD65E322487D9610801CA4FDA1D47CB197B4A06FF56092EDC6", + "fileSize": 1031 + }, + { + "name": "GB184673.TXT", + "hash": "11E5A414DB28B41004CC4AA094B5440652537A69C735E8E08FE78806B6215B87", + "fileSize": 3381 + }, + { + "name": "GB18ED0H.TIF", + "hash": "0DFE97CF57F366D7F85CCD02A08C03B303E7931B7092C8048236D8D1E36BDBA7", + "fileSize": 141140 + }, + { + "name": "GB203766.TXT", + "hash": "85EBC473821CB3854D9895ECA216B107E4FEB4686DAC3F65E04D9068D742EA9D", + "fileSize": 714 + }, + { + "name": "GB230906.TXT", + "hash": "76C82C6497EA9A413A43B1780796C5E85668D247E9F1601945DF42A458792957", + "fileSize": 631 + }, + { + "name": "GB181180.TXT", + "hash": "544C1E24B638EBFC0FB3A08D6B682A5F6A21CC038BCA50BE3EA399520CF3F7FB", + "fileSize": 519 + }, + { + "name": "GB230990.TXT", + "hash": "0F33A73E56B9466D2A83C2BF7F46D153C0BD1FBA89888A82E83B75EDCB02011F", + "fileSize": 692 + }, + { + "name": "GB1E2E04.TIF", + "hash": "D9472CA5F5AABE1E2AC95E24D6EEE4A14E330BD2D817149F0C6E7C44C620BB1E", + "fileSize": 94828 + }, + { + "name": "GB203503.TXT", + "hash": "26D5BDD2831E145B7B2C13280052B974F7365240023AE5377EA464F740AB32FC", + "fileSize": 762 + }, + { + "name": "GB231055.TXT", + "hash": "FD436F8950BFBC289F662B4221B8A382437AFF24F0ACAB67EFAB87C810A96A19", + "fileSize": 668 + }, + { + "name": "GB221111.TXT", + "hash": "9C92FB9B570819E4B4E2C592AB01C9E93BF021B2EC3DBFE66BA4E48D7068F8D6", + "fileSize": 936 + }, + { + "name": "GB203265.TXT", + "hash": "C0D3CC55B2EAFF6528405B0DC738536099B9B53B5F0C25D8449082E659B1743F", + "fileSize": 710 + }, + { + "name": "GB231056.TXT", + "hash": "339082D73B873A9634D88BCFAC6CA3D234EFD250FF22B4EFBEF668C36E7ED655", + "fileSize": 477 + }, + { + "name": "GB221090.TXT", + "hash": "42E873E15D11C59BB08AE4E1E119E6BA8F099DFF9D7BEAEEBEDC1CD08645B32B", + "fileSize": 854 + }, + { + "name": "GB202741.TXT", + "hash": "BA9823A58D600FC6AF1E4AA775B9879D64917C10148C663C1872F22D85778247", + "fileSize": 557 + }, + { + "name": "GB231118.TXT", + "hash": "E1DFFE95B5887764E7E5E0790082F7D1B9E99EC37D663A30C80BACF392B00C02", + "fileSize": 1455 + }, + { + "name": "GB202676.TXT", + "hash": "156E7C94DE07494B8F22430F9C00845055D5B37A835112A087350B90505920B4", + "fileSize": 789 + }, + { + "name": "GB231178.TXT", + "hash": "CBE597BADA534EA86B611BF1BF044466A7964CDF27A6B57911923A7B0AED5DF4", + "fileSize": 769 + }, + { + "name": "GB0EF80G.TIF", + "hash": "C8CF52BB9DAD5E87A19EC182E890719544235449235BE39DEF164166BFA187AD", + "fileSize": 28760 + }, + { + "name": "GB212269.TXT", + "hash": "8E265B74B8E4C1FD975B5D1BCC1748B9E8337BF80C77BABC2832C4CB2BC2E1B3", + "fileSize": 511 + }, + { + "name": "GB202620.TXT", + "hash": "0FCD3161E9FB00A86F65AA7B205DD46D54C3E54BED08EEECFD4F994717B28B47", + "fileSize": 620 + }, + { + "name": "GB231239.TXT", + "hash": "07EB5287FA0E0F03B36F8EFC4395654DC6AF7E444EBD5790512E709CCA16016B", + "fileSize": 523 + }, + { + "name": "GB0F830E.TIF", + "hash": "3DC5BCD29ED3002B41D5454EB7242D913870C0D5FC99371F9249AB41C7057DAD", + "fileSize": 41440 + }, + { + "name": "GB196397.TXT", + "hash": "646896392F0EB49A39107186D12E9726D00FD835A0F63440DFAE9E27E3E912F6", + "fileSize": 1028 + }, + { + "name": "GB202529.TXT", + "hash": "3D3906B4AD245B9C3261C70F87E96AC83A9896133B420963B942B296EDD3BAD0", + "fileSize": 515 + }, + { + "name": "GB231233.TXT", + "hash": "1BFFA3AF73B49865554FF8CED51DDA92DE0E976B1A622D8950C3BE8380F3B2F4", + "fileSize": 822 + }, + { + "name": "GB13D903.TIF", + "hash": "F3AF909751E71E07781349C71B428F888CD1056A8C4900F99BD5D3C78C18860E", + "fileSize": 27748 + }, + { + "name": "GB171417.TXT", + "hash": "F41F93214D395DD3F5054E96F0DC3F8976172A9F48646AB49A3CE801A5BA2C51", + "fileSize": 773 + }, + { + "name": "GB202248.TXT", + "hash": "2628F63F12CB09989ACB3276862BD31F6BD09D81A1B3E91513A8BDE21A5DACE8", + "fileSize": 1184 + }, + { + "name": "GB231439.TXT", + "hash": "C190A7EDF8E185A7E076D45D9A0245F89B2290AF118535ED4DF451AC7FEBA54C", + "fileSize": 543 + }, + { + "name": "GB220597.TXT", + "hash": "5A7EBEDCAB27A142AA3EDCBA5CF5B7B031C1E766A610484E368E997BECD7328A", + "fileSize": 1146 + }, + { + "name": "GB202225.TXT", + "hash": "BD308BA898B9B6BAFA90AB57EC2F60678A5E37661F015DBA4C9B0E940322C9D2", + "fileSize": 459 + }, + { + "name": "GB231482.TXT", + "hash": "038FE2A2B41C3890FC39D1AA792190AFEAD0E8DA9F14F225ECE588D2F3FE5DAC", + "fileSize": 1155 + }, + { + "name": "GB220519.TXT", + "hash": "0B3B3F5A204190450951423CFFCF8EBB0CA3603F581E22461F3A09C021FBC7AC", + "fileSize": 805 + }, + { + "name": "GB214897.TXT", + "hash": "3128D522CCD5A8F3E53A9708F2A0915EDE9A7E61D16265DC8EAD7B06A813A8A8", + "fileSize": 563 + }, + { + "name": "GB220430.TXT", + "hash": "E53E647839C650955DD23BB70F1415C16210F5462B3664D9F01E444F5D5A7D9A", + "fileSize": 512 + }, + { + "name": "GB224882.TXT", + "hash": "9F65108A0A5543DDE08A75006E5D8A0F5960EA0235AFC1BA98F1A7248FBA4D60", + "fileSize": 837 + }, + { + "name": "GB0F8308.TIF", + "hash": "B047C7B16A88CE68B97C8028B470C8BB60EBF75E5B7B391E2C042562EFF9C9CA", + "fileSize": 26456 + }, + { + "name": "GB220389.TXT", + "hash": "4DBDB584924B98F7A1A3E4FBD24FC7DE0F4072524A1589DDF7309333B8DE893C", + "fileSize": 540 + }, + { + "name": "GB231822.TXT", + "hash": "8B2669CB86892AA10D977BD6C07F415012F1F21B54815268F4239EE9187D1925", + "fileSize": 4023 + }, + { + "name": "GB231822.TIF", + "hash": "CB7CB5B26189584AA114B95C95917D608F7CFE444F1D7EE6527903691F9B21F2", + "fileSize": 135660 + }, + { + "name": "GB0B391Z.TIF", + "hash": "0FD08BFCB3510DA7B1672AB7A59673DB4B86798EEC8B98082D498EDD86480370", + "fileSize": 29432 + }, + { + "name": "GB220237.TXT", + "hash": "791E76C9137E3CD827E1A16AE9DF2B653155EE50E993C270682A784DE1D0077E", + "fileSize": 481 + }, + { + "name": "GB231965.TXT", + "hash": "23E8F7242E0B2D3F04C6A92949949EAEE7722F5A54E5DC8C69E57FE604E11397", + "fileSize": 620 + }, + { + "name": "GB215350.TXT", + "hash": "ED341C18979129CBA8C07712A810F58EAB65D3C52B3F142EE0FDB7E99B78634E", + "fileSize": 892 + }, + { + "name": "GB231992.TXT", + "hash": "4A4FD3E812C329FCAB4F825186A54751C719FAC0C0B0DC87B41F728E5171E4DB", + "fileSize": 1889 + }, + { + "name": "GB215210.TXT", + "hash": "C9B37E424A001987D3958C5CAFA33C401554ED97AB5D32346382CD8CDC433899", + "fileSize": 944 + }, + { + "name": "GB232191.TXT", + "hash": "9623D9EC1E5EB84C7455BD23DC29E652F88FAAE0597437AA6A90AA22BFE751DB", + "fileSize": 761 + }, + { + "name": "GB1B6703.TIF", + "hash": "88CBADA28B2FAA30193BA532A302502FB5972099B18292050D91EFFE9CB02738", + "fileSize": 61504 + }, + { + "name": "GB195444.TXT", + "hash": "03A801D1D6900A3F519ED585FB6E1D9FDAFAA3A423BCA72088928B97677E7F1B", + "fileSize": 779 + }, + { + "name": "GB193604.TXT", + "hash": "3C7690C225AA0741A9E5F5B52F9762DB53E427AEC6F382B5D7C50AB2E32851AE", + "fileSize": 1034 + }, + { + "name": "GB0B392F.TIF", + "hash": "C98535DA92030E3598BFA8B0EBD4439C23CBBE1F0195C2412557D73E1B46B480", + "fileSize": 21732 + }, + { + "name": "GB214899.TXT", + "hash": "29F8984D4BBF8E57F6EE6F15D33090FEF1062BA1582083C8212EB5D3BFB0B0CE", + "fileSize": 632 + }, + { + "name": "GB268116.TXT", + "hash": "43260BB1EAB58F020E3216376802442A71454055B2A4C58B5E787A1182DED90A", + "fileSize": 1550 + }, + { + "name": "GB268116.TIF", + "hash": "D28A93F2DF72D24CB0F5F3BCF30C50BF318FFC7874EACE70FFB26DCAA64380D8", + "fileSize": 147992 + }, + { + "name": "GB204958.TXT", + "hash": "C96190D3295A9DCE5FF75AD7CC2C7FA135C20DA54927E8F7415F7BDAFE77BAC6", + "fileSize": 553 + }, + { + "name": "GB232501.TXT", + "hash": "0EC511CADB8E22F59D69F5A27674BF9786226802940C66FF4BE9327EEC064362", + "fileSize": 1165 + }, + { + "name": "GB0DEE0E.TIF", + "hash": "1696F8477E8694CEB92DA2A3378CAF05E8EFC373CFB2DEE9A1EE79ADF7784473", + "fileSize": 25620 + }, + { + "name": "GB214845.TXT", + "hash": "9A336F0380588A007F4BCA16394B9ED60A50E9CAC2136A96029B1C3B97A29B3A", + "fileSize": 693 + }, + { + "name": "GB232502.TXT", + "hash": "0A44C04AC1F99DBA586D1F9437FCA962DE15B03DBC229C393033BB7629CA7B61", + "fileSize": 786 + }, + { + "name": "GB232503.TXT", + "hash": "D98F2B36AFE20CECA63B2B1CDB5E11F1B8C223F1C35B75C77E5AF2C8130206FE", + "fileSize": 2727 + }, + { + "name": "GB02EE0R.TIF", + "hash": "129C4BDBBC20435483A96C73698F4377C1CEE392C29D3BE78C5A66278752D739", + "fileSize": 41992 + }, + { + "name": "GB0C0306.TIF", + "hash": "972D1530C3944282F5DCD5D1941B8242E19885BA5D435313FA424CBD712B54A7", + "fileSize": 60372 + }, + { + "name": "GB401716.TXT", + "hash": "6DF741D205EAA58A94B1B64A19764F32647501472BEAE627E9DE73E2BB8FA57F", + "fileSize": 626 + }, + { + "name": "GB232519.TXT", + "hash": "1F253718A8BAFCE3D549833FF1283AC709F3F7FA44B6BBDB7E33E1D8405DAEF8", + "fileSize": 524 + }, + { + "name": "GB214313.TXT", + "hash": "F92A8FC78A69B89AB5FCE5E3DBF2D1F189ABDE3ACD0F6EF1E3C98433D5196885", + "fileSize": 931 + }, + { + "name": "GB214253.TXT", + "hash": "BC9ABFA21938042A4A637BB6FC2747F8A0DD347240EC23D716607A7B0FA9AC59", + "fileSize": 541 + }, + { + "name": "GB15E80X.TIF", + "hash": "512AE76E396B6614B6D7A4D6E2E62835A2CF6B7A91625AC97B376DFE46718D29", + "fileSize": 62824 + }, + { + "name": "GB214222.TXT", + "hash": "B9561A1DFA166BD0F84486A641E9E2A91507AE451A1DCE0EB1DE46623EDF56C5", + "fileSize": 713 + }, + { + "name": "GB15E80Y.TIF", + "hash": "DABBE17EEF13E1DC39E94E85D5C16DA2C1B31846A8FC890C43720A40A9D62889", + "fileSize": 61844 + }, + { + "name": "GB211471.TXT", + "hash": "D5B8E08370BBE97C76A5EA336FFDF9D04432137CD37B5D4FCEE86C75F0172B8B", + "fileSize": 746 + }, + { + "name": "GB15E40M.TIF", + "hash": "808ED3F40C6FF85C3891FD5C14ABC5577A729C8BB0DF9A4F91ECAAFD556E75F6", + "fileSize": 50144 + }, + { + "name": "GB240183.TXT", + "hash": "913F573009B6BC366F971DD26C0585348B576F01BCFC738F8AC6C4524ACA133E", + "fileSize": 1860 + }, + { + "name": "GB178E03.TIF", + "hash": "54147A35E087945722FAA051B275C733DB41A5982A7B2E4EC7CB26B74AAC1503", + "fileSize": 16980 + }, + { + "name": "GB211470.TXT", + "hash": "2A8FA2C9E17882E75A64A91EEF07EA8CD496E321146C0BDF8E416FFFFD35A242", + "fileSize": 660 + }, + { + "name": "GB10120S.TIF", + "hash": "0B1F46928420622C1333FCA537AE509991720078ADC24BD645FC18D4961B4C0A", + "fileSize": 63936 + }, + { + "name": "GB234715.TXT", + "hash": "780DB0A5E8EF8F07923607771060D3AF917A64CC831101660B232B4E70399FD5", + "fileSize": 530 + }, + { + "name": "GB0BF10F.TIF", + "hash": "6A24DCC10BDF5458ECF80F3DA6CD3905A62998B222F3516A21B58CA6AB4F98D3", + "fileSize": 21908 + }, + { + "name": "GB234810.TXT", + "hash": "41630CD5492D2B2FEDBFD49D29C95BF2458036EE4D5FD99458489465F0A0A722", + "fileSize": 2294 + }, + { + "name": "GB0B520V.TIF", + "hash": "D8DBCB049111B1801A558CF85443A31D472202BF5953BA6022B21193998F7DFB", + "fileSize": 59412 + }, + { + "name": "GB16931A.TIF", + "hash": "A720780A2139107615A66786F81C322534B3F9CF4B1D07C4F61501831D544974", + "fileSize": 28124 + }, + { + "name": "GB234881.TXT", + "hash": "0DD92F5326567BDD1D09D158EC20BAA3A191097EC07967F7059ABDC8212686DB", + "fileSize": 1083 + }, + { + "name": "GB211F0X.TIF", + "hash": "07B63ACDB2F30226AD2E373DACEABFE6AF7CAE0C6547981F152A21A9AE8F25AE", + "fileSize": 145152 + }, + { + "name": "GB234978.TXT", + "hash": "A7C5BC895A5A4F9F6F24314F079A6F78B22F89E9616B142EBF91CA58B66E1A67", + "fileSize": 574 + }, + { + "name": "GB0CDE0N.TIF", + "hash": "11BF3C63B79808A1C8B8A797E94FF34122D0F394B1CAAD6FA4D42C5AF9A57948", + "fileSize": 30320 + }, + { + "name": "GB1E2C0G.TIF", + "hash": "8E29CD2C29A771614B1861B6C10F061F0DABED03B4592376D56BA8C3CD4C2443", + "fileSize": 39620 + }, + { + "name": "GB183306.TIF", + "hash": "84BDBD37C9F02367ECE0FD6CCE90A896E54FFD60D34CC754012783140F757FE3", + "fileSize": 94862 + }, + { + "name": "GB1B1A02.TIF", + "hash": "857AFEB7319A605A7F70F49918B517A6139AD5E517028F4AAF83A0F2A263D21F", + "fileSize": 23528 + }, + { + "name": "GB13A802.TIF", + "hash": "B85CA38B2428914E95528802658BAA6ED689E59E803B9A9FC5CD0F48EAA96E64", + "fileSize": 50612 + }, + { + "name": "GB235044.TXT", + "hash": "1BBD21E935B5823738EDD9B91F15AE5278D4ACD91F8D59A3DE9A6D58E698D08A", + "fileSize": 543 + }, + { + "name": "GB0F8203.TIF", + "hash": "E6B9D2A4DA20DF869E42286ABF45D034AE964ADD3918AAB9B0CCC3B7775F6F6E", + "fileSize": 28188 + }, + { + "name": "GB0EA902.TIF", + "hash": "33CD0D4CA6621B8134EB563C8C31BA6368B530A498EE4476FDA91B2D93A80DE6", + "fileSize": 13876 + }, + { + "name": "GB235060.TXT", + "hash": "2F36337CF181FF475CE9302245702539ED0A7A9B1F87B67254AB36E723D873BF", + "fileSize": 522 + }, + { + "name": "GB13460H.TIF", + "hash": "410C997EC7B7CB080158FEF5C51542EDF79A18A2C56E14304FB7BFC6C53DBC79", + "fileSize": 83840 + }, + { + "name": "GB235054.TXT", + "hash": "822C197396AC58264AA711CFE8A9142C1ACA7CF769C6566BDD00CB26362817EF", + "fileSize": 671 + }, + { + "name": "GB0B520U.TIF", + "hash": "1F037F50F220BB7052D0A9378B332C5DED152131D409B34C6ED36E759CA0F73C", + "fileSize": 104072 + }, + { + "name": "GB200444.TXT", + "hash": "A0167B8E824714EF819D9AE710A6D6C1990A4EABFEEAF9354A8FA2106C299859", + "fileSize": 1051 + }, + { + "name": "GB240109.TXT", + "hash": "54934B2953B083C64B38593B2FB759A77D7F26C024E6A185913D75AB916CE452", + "fileSize": 586 + }, + { + "name": "GB071E04.TIF", + "hash": "5C6A811FBB9DFB569BE59A26E7CB406E73CB89F652E0C6785CAC988F1F4797DD", + "fileSize": 90198 + }, + { + "name": "GB13B202.TIF", + "hash": "AA6FF6FC10CAC7623C462F61288A5783E1DA0423898CCC806C11FD218A683FDF", + "fileSize": 33384 + }, + { + "name": "GB212042.TXT", + "hash": "B67D39ABBD8B84460138E21623CB005DC1803E8EBA7EE20514E830C8A924D7B3", + "fileSize": 679 + }, + { + "name": "GB034E11.TIF", + "hash": "8A6243EF7C08F16938EDC5492A317B11D4DAEDBA81403BB06F10380FB83C3A62", + "fileSize": 32984 + }, + { + "name": "GB0B520B.TIF", + "hash": "AE4E61577D3961E39B7EBDA5F025EDF6CF1949006C95B4DF962BB50A07C8BB8F", + "fileSize": 27496 + }, + { + "name": "GB0D0B18.TIF", + "hash": "AD6C469A67414AB3FFC8DB0485B099B326E69A4C79A0F234CFA352CD12507343", + "fileSize": 30904 + }, + { + "name": "GB240136.TXT", + "hash": "2DF0323C38D29FDAABF65847B7D6B16E50583790E1005AC069AC6A08EBEDBBA6", + "fileSize": 2076 + }, + { + "name": "GB211823.TXT", + "hash": "17F27C08D87D25C97AFC0ACCEB7FCA268712251E2E9DCC100C1F804EA1D2B570", + "fileSize": 567 + }, + { + "name": "GB268216.TXT", + "hash": "4FFF242DEEC5EF6E5DB40D928C3B8FD008402565F774E87796A04E8650F777B5", + "fileSize": 1528 + }, + { + "name": "GB268216.TIF", + "hash": "C750D2AC9D6AE496C1EFEA3CB098C5889ABFE197372F51DC1FFA3D3FED6A77AA", + "fileSize": 120972 + }, + { + "name": "GB0D0E1J.TIF", + "hash": "3AECEE2FFB545048D4C2790DD50B645459829FAD62BA7458C445FB706356A757", + "fileSize": 59180 + }, + { + "name": "GB0C0407.TIF", + "hash": "757AFE77CEAC4E3D77FE57A76EF69DAD38306C9BDECD3D7980EAD5787A67B3E3", + "fileSize": 87852 + }, + { + "name": "GB211435.TXT", + "hash": "F83C2276E9FD161FBA5516B190A04AF7C4BBD8A31BE014F77F5B31A6E976CA7A", + "fileSize": 2015 + }, + { + "name": "GB0DA902.TIF", + "hash": "EE213F8AEA7A8A833CF5055A916656951EF255F8C46767588A8DCCF6169ACAEE", + "fileSize": 14772 + }, + { + "name": "GB23490I.TIF", + "hash": "213473E8BDEB94AF09DBEA287C1EE6DFFCE3B8DE42EF8480E5012F01414D6304", + "fileSize": 323470 + }, + { + "name": "GB1B620T.TIF", + "hash": "18C3263006573E9671ADA4E7A4A94226BB57F924257D39C6397356C6DAAAEF35", + "fileSize": 459504 + }, + { + "name": "GB1D6C01.TIF", + "hash": "DC2579F801293E52E5F45C967EE1D0BB1B4B7D8E48EF0DD3D40ED89467EB5532", + "fileSize": 25548 + }, + { + "name": "GB0BE40E.TIF", + "hash": "BE80A9474BC0AB4838FBD26DB0AE65883143EF54C43A5FC01018DB24B1B04919", + "fileSize": 54222 + }, + { + "name": "GB02DF04.TIF", + "hash": "ED0E688187A55F6E1C29B5C13B9622DA7E2AE00B1963572AB9C7A6F54909ED1F", + "fileSize": 67660 + }, + { + "name": "GB13AA01.TIF", + "hash": "1D5ED922093949DD98593E425E2A56D9EFCA8CAFD94EC97498DA3E0A73FB22D3", + "fileSize": 31688 + }, + { + "name": "GB21F601.TIF", + "hash": "AE9587BFF83C10DC8D2EDEDFFE064B2BEE8C8CFB0E1984D2662871E5E757A9DC", + "fileSize": 62528 + }, + { + "name": "GB0ED902.TIF", + "hash": "7E49D4BCE909B4896FE1BE62351B15263D292AB06265604BCCCB63FD73B99CC7", + "fileSize": 49928 + }, + { + "name": "GB0BAA1M.TIF", + "hash": "378A2E681B17B337B2011CA57E671044F46D38DE5F00B76F6FD9CACD22C68B8D", + "fileSize": 27244 + }, + { + "name": "GB0BFD0A.TIF", + "hash": "31D4C3568671BD200579C973C5FBC73B7ED7A467B7F57090BF13CAB033C3D8E3", + "fileSize": 41472 + }, + { + "name": "GB21EC01.TIF", + "hash": "E2A775B7B42C0F90668DCCAAFBB3806730CD786A8F608BE9CB61468C7EB1A17D", + "fileSize": 92478 + }, + { + "name": "GB25C902.TIF", + "hash": "50F1D7D112A8D655E75482FFF0A486B946E2A9448A2032FDCBE77CBC6C90728A", + "fileSize": 203304 + }, + { + "name": "GB13450D.TIF", + "hash": "944F368C60896B9E6710EA080A4BF8B5F1CB2E0D4CCB2F453F0D802A418BF13C", + "fileSize": 18076 + }, + { + "name": "GB0DA01G.TIF", + "hash": "777585D8AE3C37ED6C945467D8B59658B0E45559EF53B522D0A5AC3E81BA25B4", + "fileSize": 35464 + }, + { + "name": "GB08CF0F.TIF", + "hash": "09D63C0540E17121B293D10B499BE8F7A8A29EC10A417FDD5FCA03751EDA38D5", + "fileSize": 55032 + }, + { + "name": "GB140C1G.TIF", + "hash": "1958AB3D9A50575EA745BEA6D57DAE6EFF9615F33A18C84CAED5E3F29C568D88", + "fileSize": 92202 + }, + { + "name": "GB102702.TIF", + "hash": "48A7E3B976395843753B2194C96CF3347E25AC5E59C87E3F8D3889FFF63289F0", + "fileSize": 47712 + }, + { + "name": "GB140C1H.TIF", + "hash": "221082A4080F2375AC8973F91E6F975B3D97D53488C21D341A62DEEF51FF1640", + "fileSize": 76462 + }, + { + "name": "GB0DB81J.TIF", + "hash": "DDB292BE26848A6D25652CF10F9ACA5E58D76EB0364810F97BE304E85E96DFA0", + "fileSize": 37864 + }, + { + "name": "GB11AA02.TIF", + "hash": "7DDEC059A2AA070450C2E8A6C00C67CA6B05713CF902688C629CC1A95EFF462B", + "fileSize": 73252 + }, + { + "name": "GB170D0F.TIF", + "hash": "BFA12E6E064A376FA7C9D0C9F3D2F9508D62BE66F3C5510EADA39D442C2DF75D", + "fileSize": 25456 + }, + { + "name": "GB136F36.TIF", + "hash": "1958AB3D9A50575EA745BEA6D57DAE6EFF9615F33A18C84CAED5E3F29C568D88", + "fileSize": 92202 + }, + { + "name": "GB1E2C0E.TIF", + "hash": "ECD8D96C2640460FC900B3ACF944B1E690D3D8EE85389D05EFF857BB3AF78C25", + "fileSize": 13630 + }, + { + "name": "GB136F37.TIF", + "hash": "221082A4080F2375AC8973F91E6F975B3D97D53488C21D341A62DEEF51FF1640", + "fileSize": 76462 + }, + { + "name": "GB0F9C0B.TIF", + "hash": "9D945F19A53F62936C19F040D8B030C414D05B54DC5D43227CCCA9D461F0158C", + "fileSize": 16732 + }, + { + "name": "GB568616.TXT", + "hash": "04D4E1068B8BFA74CD670E975E932833702DDD60FCA8DDBCB2AB89FD41851D9E", + "fileSize": 1755 + }, + { + "name": "GB170720.TXT", + "hash": "5BF87C9602588E6074E9DC32CF845E5A88B150F1C513A929F4233167799C0AB9", + "fileSize": 789 + }, + { + "name": "GB056A01.TIF", + "hash": "2E450271370F63A3DE1ECC4C9FDC50F6E2B61ABE54E54B93E53986C7247BD5F0", + "fileSize": 29340 + }, + { + "name": "GB0B8F1B.TIF", + "hash": "D5716698FB75F36C93FCAF2070284C644464E638A3CC012586B58FE965F09175", + "fileSize": 27096 + }, + { + "name": "GB233046.TXT", + "hash": "FA6497D98F20020FCBEABB10069FE67C07302D25BCBA494100D6A2AC35C6C4BF", + "fileSize": 2093 + }, + { + "name": "GB0D0E1I.TIF", + "hash": "BACE77B8218475AB2A49CCACCDFA9BFE68DB890E0F8B3A2852CBFBE9DA536527", + "fileSize": 88372 + }, + { + "name": "GB0C2B01.TIF", + "hash": "0C7052ACCF49AB84AB2D15CF593C87EA8D149F478B9C3EC7505135A526C68823", + "fileSize": 14504 + }, + { + "name": "GB0BF10G.TIF", + "hash": "4A2B80157692C3E1070BA9DB0ECF95F9DD8A9F19E2DF605F1F175313C5C75C23", + "fileSize": 25376 + }, + { + "name": "GB182263.TXT", + "hash": "E149592E93967B57A2C8421CEAA28BB6501411D9E743B53D6C8F3744E95474AE", + "fileSize": 562 + }, + { + "name": "GB233211.TXT", + "hash": "572045C55DE195B1A9232630B583782450E4842BCEE080EC9D3B3EDB161A4D85", + "fileSize": 527 + }, + { + "name": "GB19BB0K.TIF", + "hash": "938DCAD5505F1B0DEFE6D75C1E4A981F04DAB84A76663FC0F5AE53688331F6D1", + "fileSize": 84166 + }, + { + "name": "GB092C09.TIF", + "hash": "6FC8A7FC382680FD6608263DEEE201850F1398E365AB6EB21707BE34AB28779D", + "fileSize": 48120 + }, + { + "name": "GB056A05.TIF", + "hash": "9AA120B6E6B5036BCF0971048A1BC1422B163E2A880261A3D98F2D89AFAE498B", + "fileSize": 24264 + }, + { + "name": "GB181401.TXT", + "hash": "4F1D8B739D69A2548A6C94851D719A57B1FFE3BF0C2673A42AF27DA7CEC0FA11", + "fileSize": 5119 + }, + { + "name": "GB233241.TXT", + "hash": "07D79909D87B919F905618196004EB2B6DAF401D5E9DD01EB1493B7407D2EAFE", + "fileSize": 752 + }, + { + "name": "GB0BEC0D.TIF", + "hash": "8C2A742BFC3DF967AF04BFBEA1662FD11195F26415D76F0E6E3D76D7EE910E7C", + "fileSize": 23008 + }, + { + "name": "GB0F6C1S.TIF", + "hash": "B036E3984BE0F371AC96E065F0884A4634735A2FADBD9C583EA9885B8711A215", + "fileSize": 126716 + }, + { + "name": "GB183341.TXT", + "hash": "32899D729F32E0D9E12FD32DF0E85031BAE4DF924C9153FA11862E381EA2F87A", + "fileSize": 748 + }, + { + "name": "GB233267.TXT", + "hash": "38F553230B336EC97A91E7D6629CB7ED6A624EF878E24190057CA608956690DD", + "fileSize": 904 + }, + { + "name": "GB0CDE03.TIF", + "hash": "01B7D27DF86A71B66619D0FEC5EFE0F183F335FB2AF6EBB03F25A9763EFD9CE9", + "fileSize": 30820 + }, + { + "name": "GB216F02.TIF", + "hash": "23170C1A8A77F4EFFB912D808ACB9C1DD62DDF41D4EDDED0CB1520E0E93EEB80", + "fileSize": 26810 + }, + { + "name": "GB0F1A0Z.TIF", + "hash": "DCD6FF686BD132D929DA19DE675E2CFE4BC0D5B29CA9C2C113E2057045BA382B", + "fileSize": 33404 + }, + { + "name": "GB184195.TXT", + "hash": "579B1C8996D9B1A65F1C4CF9A78ACCD992F895FC2C1CBA2AA6659497830FCE5C", + "fileSize": 475 + }, + { + "name": "GB233299.TXT", + "hash": "0F61362FE48958E1879CBAA048039924FDBF6307AFCC8EA6C153289FF94325CD", + "fileSize": 505 + }, + { + "name": "GB0F8201.TIF", + "hash": "8CA0D79236BC4424D501FAF3A267318B8F9C3493F93AD2751BB589ED5F1173FD", + "fileSize": 39708 + }, + { + "name": "GB156C0Z.TIF", + "hash": "5DBA4531EAD7C6562BC2B995021995B65E889F21F47A43C31A03737E751AFCD7", + "fileSize": 37496 + }, + { + "name": "GB221260.TXT", + "hash": "CF1EB207A8009CCD04C24261D624A3A4563DAF90C9AE0487CF2286FFDFA0D095", + "fileSize": 691 + }, + { + "name": "GB233307.TXT", + "hash": "A9BC08F50E5FDFF70CAE0C8FF1B4490298CDDEDD1EC8922A9477A2A72D4B4CD4", + "fileSize": 563 + }, + { + "name": "GB1B600B.TIF", + "hash": "2C6736840FBEA4576B381E5EDE17E664D2BB2B11C08395869606EB7D4390E1E3", + "fileSize": 34456 + }, + { + "name": "GB22BB03.TIF", + "hash": "9B1B26A498B523BDE57A35E5460ED9FF189E92F65FA821933702CF64D678F5EE", + "fileSize": 53488 + }, + { + "name": "GB02BC04.TIF", + "hash": "F631EF164E2D8EC685F3136B88FF7D5A895C6C7FF5C4A0CD5BF8EC9114E0AFB7", + "fileSize": 27496 + }, + { + "name": "GB221484.TXT", + "hash": "7BB50EC705FA357B78A3A31A2CE86BC34E33A28A5AE16E53E56D1F5E40D03C78", + "fileSize": 2234 + }, + { + "name": "GB0EE917.TIF", + "hash": "9A51078E22CF2DF1DEEEC481F2D7CB529EA85AA0A6186D730690B260436B1A8D", + "fileSize": 45164 + }, + { + "name": "GB0DA01F.TIF", + "hash": "4416EFE648CAA965C76D56033514CFCEB20093F4F01EB568404D042DB1521472", + "fileSize": 49624 + }, + { + "name": "GB233342.TXT", + "hash": "0B38AC11B1388DFACBD634B17CF42FA2D67412101FCE25BCFC28A2E0ADA63BEC", + "fileSize": 772 + }, + { + "name": "GB02EE2Y.TIF", + "hash": "B29F8BDA0B117C90D9DDEBDBDED47D0F3C1EDCABCFDE5E2971E9E3512C70D20C", + "fileSize": 337378 + }, + { + "name": "GB221531.TXT", + "hash": "35EAEBA5CD4F43BA0ACF0E26ADD97A9D7A4591DF33982CAEEEBC1EBC22B8E4D1", + "fileSize": 443 + }, + { + "name": "GB233360.TXT", + "hash": "D41676F3879668A25E091B9C373BAF014FDC3A3F6BFF61A610D446359586F42B", + "fileSize": 937 + }, + { + "name": "GB02DF03.TIF", + "hash": "D6BFE7028C92A7E95802E6CA255F8F26768DB1B3E5BC3422714637BC3E9074E6", + "fileSize": 58200 + }, + { + "name": "GB221534.TXT", + "hash": "A873A9AD72A5817EA2F0ADE56FF7896EB67AFB03DD656CB3CC7F3BDE48B4AC52", + "fileSize": 587 + }, + { + "name": "GB101206.TIF", + "hash": "0906FFA44C0E287514E2BDA26C3D8AC4AF5AA60360E0BF0AA68BA1AC22DCB20A", + "fileSize": 33296 + }, + { + "name": "GB233389.TXT", + "hash": "9C6943A987A486572BE5BF634A5C95772E12621B4B34B8112AC2A736A5A119C2", + "fileSize": 824 + }, + { + "name": "GB216F01.TIF", + "hash": "F050D730034051B4DA133DA2675511C66411439071E31A6B1BEBF01B68A76659", + "fileSize": 18184 + }, + { + "name": "GB221530.TXT", + "hash": "0EC67945BA5035A2E4411A75983C0FE4C03BFCA71DEC729C8B4EDE7F999026A1", + "fileSize": 652 + }, + { + "name": "GB233417.TXT", + "hash": "66631D0B312D3206FC477A48AB82D7A307D5D4E0BCCBF7E4818AB56248A6BE00", + "fileSize": 525 + }, + { + "name": "GB11B802.TIF", + "hash": "4DCD51F5FCB660AE91538ED56930D85E3096297972C7F0F9AC148B5000C139F3", + "fileSize": 24736 + }, + { + "name": "GB0C030E.TIF", + "hash": "3D3E48A7A6F96A93A9CC4913A9EACEB60A36263183E21D39EB9016239FA8E0A7", + "fileSize": 38736 + }, + { + "name": "GB221539.TXT", + "hash": "00EEFEE584C14E6D3EA04F848974AA843A8A1FDFDA82EA88E8D1CD786E210539", + "fileSize": 1118 + }, + { + "name": "GB233358.TXT", + "hash": "CBA206FA85D10C295E8C8845BF951FAF9A4AAC8CBD7BFC175478FE045F22EF21", + "fileSize": 1110 + }, + { + "name": "GB221591.TXT", + "hash": "57C16A59FBF847C8D96BE62FC12396D53DF9EB1547FAC47345B66959A87E4442", + "fileSize": 7368 + }, + { + "name": "GB221591.TIF", + "hash": "787BB702B9BA55EA25C64F65277937EFD159E88B2E9129097E52C6425976620B", + "fileSize": 577322 + }, + { + "name": "GB11BD06.TIF", + "hash": "BB00CC8BB89C030E7A8466E20ED0CFE784190B35B6D00B3BE532A243475FBA53", + "fileSize": 39148 + }, + { + "name": "GB131602.TIF", + "hash": "F58B671ADB28DA5D9D48BE481A8C5AA4D3DBDEC6CB49E1F1B54BC467617511B4", + "fileSize": 25376 + }, + { + "name": "GB221873.TXT", + "hash": "A6E2C767AE3D3C8E5E82A84AFA93E4E69431B989991B44BE21937E5135581FB1", + "fileSize": 679 + }, + { + "name": "GB233447.TXT", + "hash": "31A9D65108F9BE765DB4F2471BC6D03D2FB6E438DE93850295BDAA985FD7656E", + "fileSize": 1981 + }, + { + "name": "GB178E0G.TIF", + "hash": "0E6F61FC9D72C7AED7120E846B3A0AD6BC735176E209136D8BF23AF22D4D914C", + "fileSize": 26184 + }, + { + "name": "GB221911.TXT", + "hash": "52F6441DCDD05E1C5F0F7D3FFA0BDE99D12E0E838321B6D1938BB8DE33B9E73F", + "fileSize": 5292 + }, + { + "name": "GB221911.TIF", + "hash": "ED4301CA1A0F8E4979A5D5C2E0880E3DD992F5758BDB3252BDF0AA0D33085CE6", + "fileSize": 304806 + }, + { + "name": "GB0BE60H.TIF", + "hash": "F061D71C93237A32FF26CE490353475101346F8E76E30C595ED887550BBA7EC5", + "fileSize": 21616 + }, + { + "name": "GB249C0B.TIF", + "hash": "DFC03975951FA30AA335FAF6BA1532B1415407840381D0B86A482A9567398A21", + "fileSize": 20828 + }, + { + "name": "GB0B381I.TIF", + "hash": "E9BC5DC0771BC01E099BCBF29857778B68DFFDC3E067325E9EB516E48D49A30C", + "fileSize": 22600 + }, + { + "name": "GB0D0B19.TIF", + "hash": "740BABE2C3433AD85A63636F5A363C0EDC20AE5BE4DB1FEE6D3D43F2EF3373C5", + "fileSize": 35628 + }, + { + "name": "GB249C0C.TIF", + "hash": "3C446CE14B5BCA57ECABD9EE67D613A8A96CD7300285E8D4C2232C0921D3DA88", + "fileSize": 67458 + }, + { + "name": "GB1A5406.TIF", + "hash": "F82C3735B099E26993DFC8BE4005A26A72A3544050A938E7F9C58378BBBD1C2C", + "fileSize": 73208 + }, + { + "name": "GB02DF0D.TIF", + "hash": "A1E2DE6112AB349042B2BBC7A6D3E51924336169BE8D1A073E11EC9573BFCF8B", + "fileSize": 29516 + }, + { + "name": "GB233494.TXT", + "hash": "492993AA57F5ABD0D791B17D7F3169E7F0263764D38BD3435E35EBAC1077EACF", + "fileSize": 687 + }, + { + "name": "GB178E07.TIF", + "hash": "FF18E7E3899E5754C78B3507EB768341036D4ED5947B2657991773350E0C0BB0", + "fileSize": 45024 + }, + { + "name": "GB0BF802.TIF", + "hash": "C88E823DE3BE4BB89713C454A1E50DD357CD3DCEF867888A3F7AC27FF40FD3BD", + "fileSize": 14476 + }, + { + "name": "GB233527.TXT", + "hash": "4B74E249762ACAA9B907AE75FD4ADEC9D47CF59D8F6A21927EF93109868BD28B", + "fileSize": 808 + }, + { + "name": "GB183056.TXT", + "hash": "3CE4C3D895E3565D78669F38B4EF62032CA4B70F97BF83ACE29BE57DB3D060F9", + "fileSize": 507 + }, + { + "name": "GB233610.TXT", + "hash": "D1B626928B274351D2F753281678242C5DCD0C8639A0042A64185A5FD768CE17", + "fileSize": 510 + }, + { + "name": "GB1B6009.TIF", + "hash": "2CBFB5F3D429BB469EC999C6BF212DBA9408E695EC62FEE2930C0F2ABAC601CB", + "fileSize": 38788 + }, + { + "name": "GB233822.TXT", + "hash": "712A9B72028EE26906FDA650BC533705F2392BE5D1FA5F9961BC10D2A61262A3", + "fileSize": 536 + }, + { + "name": "GB071E05.TIF", + "hash": "0D51099DE437B4710F8AF9427CB30274AF9A8110C0B6D348C2EB1F762E306799", + "fileSize": 20716 + }, + { + "name": "GB249C05.TIF", + "hash": "47A581371CD03B6323DD1D2B5F55593F103EE4709DA2DE06F668EBB08D017B58", + "fileSize": 202158 + }, + { + "name": "GB0EA903.TIF", + "hash": "6630EF42DA239FB83C2C4664F1946FBE07AEFA1F5EEF5517D1B28C267F04F3EE", + "fileSize": 16788 + }, + { + "name": "GB174859.TXT", + "hash": "346CFD6BECC364F5E0976A1B98738AB2581C71548ABCA8A1ECE26E1E2362E39C", + "fileSize": 513 + }, + { + "name": "GB222172.TXT", + "hash": "717354B4DD54B9DA1D6A6594ECB1C92371C86F027BA8FAB591E6F321E7391384", + "fileSize": 686 + }, + { + "name": "GB233917.TXT", + "hash": "A4A8C3A59963E54CE5F4DB6671D8C522D376556C03249C8A57CC5B3A4951B6E7", + "fileSize": 824 + }, + { + "name": "GB056A09.TIF", + "hash": "F49CA4D141DF76489B520470E0DAA7E89EEAC2BFBD5C830BE54E1EB3DD90F915", + "fileSize": 32136 + }, + { + "name": "GB174085.TXT", + "hash": "1B3D057478BD4C6ABCD89F63E4745D6CC38F616FEA7DEBF96460B334F7B4DACB", + "fileSize": 502 + }, + { + "name": "GB222199.TXT", + "hash": "917FB7106893782BDD867B3A98076CF47FD20C17A185BFEF893CF7362568FE6F", + "fileSize": 631 + }, + { + "name": "GB233935.TXT", + "hash": "B97613AD29222A3483592928CA7409A722AE7BB40CBBA0417D01BE773EA15E9C", + "fileSize": 664 + }, + { + "name": "GB16931B.TIF", + "hash": "C4D419D1C2C5B2FBCCF86297AD5D0C8CAD5484EE06AD51796855ACB5E6121183", + "fileSize": 39640 + }, + { + "name": "GB173651.TXT", + "hash": "C5E1FFD0C74D3C0A9FCE3E749F2DDE8B328471933A8B1E920FAD37AEC3A18290", + "fileSize": 3734 + }, + { + "name": "GB0CC909.TIF", + "hash": "3C484BB25B31ED8CBC3211A86902FCFA1D63524CEE20C4D3D3C7A71022CB6E62", + "fileSize": 54472 + }, + { + "name": "GB222153.TXT", + "hash": "1D17B67550FCFF9F5E10A99B6315094CEE5D1726B0EB2988FECDFCB7C14BD54D", + "fileSize": 532 + }, + { + "name": "GB1B6801.TIF", + "hash": "32343F752688DA987D4B3995F5CA2684F7D843035FFA8A0E95F604494F6E9142", + "fileSize": 51876 + }, + { + "name": "GB233963.TXT", + "hash": "A4FA81708E372EDD226657094F9342B946B0300774F98949BEFB692E64669B26", + "fileSize": 1098 + }, + { + "name": "GB17480Z.TIF", + "hash": "B15EA33824F51CDF50A644C9F1016A44A50697049E03C57EAD3AEDD6AF557BA7", + "fileSize": 53252 + }, + { + "name": "GB202024.TXT", + "hash": "FC9C9275BF346D510E7BD120119F6363A673C81F5A9CF9EBD79E75E6EA806CAD", + "fileSize": 1297 + }, + { + "name": "GB233994.TXT", + "hash": "DC0F08D00CA847968F8D0A02392856FBC4FF2021D74627C872A3CB34433983D9", + "fileSize": 2405 + }, + { + "name": "GB205801.TIF", + "hash": "AC9CB1D849DB99926C27EAB00C1187CC00153AFC11BC26BF93383ABFA694FB19", + "fileSize": 99512 + }, + { + "name": "GB0C0505.TIF", + "hash": "C39D280F9E5DB606C215D9E034B75BFDD9F5874C2B64B32E708DD85E0544430A", + "fileSize": 19748 + }, + { + "name": "GB201818.TXT", + "hash": "E46627B7D2CDFB3CB336D8AE66CFAAC9292F997943E54CBC8EDD2D1C62B80785", + "fileSize": 543 + }, + { + "name": "GB123E0N.TIF", + "hash": "D7EA61076575644786B4E24DA17A82EC9C78AD37BFB21DE7A9711E54AB7F50D5", + "fileSize": 52304 + }, + { + "name": "GB222220.TXT", + "hash": "3DE6077D6CCE9FB6FCAF2E7651FEE5961D79B29EA61539EA174E15B567A5E0E3", + "fileSize": 465 + }, + { + "name": "GB234000.TXT", + "hash": "DB408C380BC5348161213541336E4FBD768A571C6356F3CB5BD817F945227202", + "fileSize": 1076 + }, + { + "name": "GB170D0J.TIF", + "hash": "9812B480996382A45230914372590246784E35FEC45318671D087B562FC516BA", + "fileSize": 20860 + }, + { + "name": "GB18DC11.TIF", + "hash": "52AD7C89899465EE901C39022ED20C20EC96CD8745C82FE028721EA5475793EF", + "fileSize": 536774 + }, + { + "name": "GB10370G.TIF", + "hash": "2D1962532A922D8E5FE7EB75806828572F042577174130B1DE6AD7E8732D4C99", + "fileSize": 29296 + }, + { + "name": "GB201543.TXT", + "hash": "FAECBFF0BF8BCB417909595A6D83C17A63D2AEFE6875E655B05762D18935178E", + "fileSize": 583 + }, + { + "name": "GB178D0C.TIF", + "hash": "328C7BE948AFE1E0C342ACBBFF2DDB8C3B925195B2BFE098059E1AD7DF4557E9", + "fileSize": 62528 + }, + { + "name": "GB185548.TXT", + "hash": "2AD2EA2FBAE525FE6922B9955343FE76BA627DF9900B505940FCFE7B567632AE", + "fileSize": 671 + }, + { + "name": "GB222728.TXT", + "hash": "F95245ACE80035008F985A8D55DF591F8E7E2766BCE6CBD3A63A3699FFA10D4E", + "fileSize": 508 + }, + { + "name": "GB11F31L.TIF", + "hash": "FBD6A4D5C783E1DEE20EC1ABBDE6DA5DAE939E63428861174E2C3923DA480438", + "fileSize": 25272 + }, + { + "name": "GB0C050A.TIF", + "hash": "DB9BD6503B4AAD1350EAECCF59EA882D486C5864107E60AB9585B7822E83E452", + "fileSize": 52560 + }, + { + "name": "GB224288.TXT", + "hash": "A80F65086D7D6DBBF5B84A93503890612C39264F41730D026C499189FEACE4C8", + "fileSize": 523 + }, + { + "name": "GB201526.TXT", + "hash": "961C35CEA0D81268CF67853E367F3A633EDA90A4EFB5E467E12C12E4AE91E57C", + "fileSize": 917 + }, + { + "name": "GB192869.TXT", + "hash": "7C8607F21B04032427EE3509DB5C171B1F6BF9C7B26A3CA913CAA0BB780D9918", + "fileSize": 739 + }, + { + "name": "GB192660.TXT", + "hash": "BD1F4EA8337D6AED5DE30F55C515828995DE1F75951D13928111181BE45E313A", + "fileSize": 489 + }, + { + "name": "GB102905.TIF", + "hash": "DD25A11207E18D092881F3D794EAE7C48635F1FA2443657A90983CA321B1B8B2", + "fileSize": 45732 + }, + { + "name": "GB234091.TXT", + "hash": "7D1BD390B8B97312FA900791026D73117B0E9C3DE5D38E14B1143CA0FE2F743C", + "fileSize": 6317 + }, + { + "name": "GB169318.TIF", + "hash": "E9BEFDFED7F101584C8D5A6B14C4D297A192BB82A7D907A6581DE3546A025F5A", + "fileSize": 39964 + }, + { + "name": "GB0F511C.TIF", + "hash": "5CB96273067874DE573B1C9924CFBEF3F3ACD62F0807E1D06F83868F4856312A", + "fileSize": 37480 + }, + { + "name": "GB0DE20W.TIF", + "hash": "425F302A35CAFE9C296AC1AE8EDFDEEBE34E11B46C99F0A7E2C979EF2528DD23", + "fileSize": 54484 + }, + { + "name": "GB201352.TXT", + "hash": "424105597FA033695A77ACAAC603E2C942DA5E68AB3F6A6ECFDDA6FB7543E70A", + "fileSize": 598 + }, + { + "name": "GB169308.TIF", + "hash": "AABAD59B6E6ECF73594DE770E3A0E65838F39B2DC529135410D5ADC5A9078E8D", + "fileSize": 61524 + }, + { + "name": "GB234029.TXT", + "hash": "429E33BDEB96A23C2D6C79C35857882CEAE7E706ABF98826FC5754F772C9B77D", + "fileSize": 572 + }, + { + "name": "GB08A90D.TIF", + "hash": "4C895C89A21B879E7E399906CD7E99A9F7022AC75C799AC6A9F5DE57D835B119", + "fileSize": 33268 + }, + { + "name": "GB11B603.TIF", + "hash": "4F1178B58C5342F5A994E6962164F6270766438201488A3A7F61B4D2CEFF4F15", + "fileSize": 35104 + }, + { + "name": "GB0B8F19.TIF", + "hash": "7B9CD546559A469C8D7F1FEDDB69D728D7FD3BD96A6B28CE3DEB6DE353175685", + "fileSize": 23936 + }, + { + "name": "GB0EF601.TIF", + "hash": "30533D610705C35FE4E1C505FF4EE0A2576A187FE4E854CE47C8380E58A9BA2A", + "fileSize": 20396 + }, + { + "name": "GB0D6B0N.TIF", + "hash": "4CC0B0228DD457B68BE0969C3939D84C002F88DDF0C6DE2743AEF4481B836080", + "fileSize": 15356 + }, + { + "name": "GB234103.TXT", + "hash": "9A9F05FAF2139C59C55CE13B8D9BD7457CFFF86E4722A5A4A504895C5A4F08D2", + "fileSize": 8854 + }, + { + "name": "GB0F241G.TIF", + "hash": "137EC6F07230A16D190C81D3D4A3F2263EE3464D90BD7A8A1B544556F8E0091D", + "fileSize": 62228 + }, + { + "name": "GB13A701.TIF", + "hash": "1CCD0B235CDFD022301AF85FD3860897C3271176741FAC2E7640971259A059C4", + "fileSize": 33072 + }, + { + "name": "GB234153.TXT", + "hash": "5D1D897AF62C9D241F6BEC53BBE141F185717A5BDFA5F5B7B42641DF7EB5103C", + "fileSize": 598 + }, + { + "name": "GB1E2C0D.TIF", + "hash": "1662EB241F4B83ACB799DC04B9D4E98DD9417C3CA96FF4338E2B3BCFE6DC7A93", + "fileSize": 12700 + }, + { + "name": "GB27F702.TIF", + "hash": "369E7E7684E4C44C2AD4744B5382E0D6C9CCE34AF4A901E5730088CBB2263933", + "fileSize": 41288 + }, + { + "name": "GB211304.TIF", + "hash": "C7332E9A9B9E55AD0A5360D24EAF5ED328B1717D28C6DA07BD04F12235FCA9AC", + "fileSize": 13956 + }, + { + "name": "GB234176.TXT", + "hash": "AFCACD6F056C2DAC13D75E589525745863A71F2B6AA43F3A5FEFDCD01B4CD95A", + "fileSize": 2326 + }, + { + "name": "GB07E41F.TIF", + "hash": "4DFA3C840CCC442982C1DA4B1ADBA038E78D0FA2F787244AE897DCF6277BC01A", + "fileSize": 179414 + }, + { + "name": "GB22BB04.TIF", + "hash": "58287B8E8D8137B029CCDA2704C6BDB717410DA86AD9694C787C338D942BEC18", + "fileSize": 32736 + }, + { + "name": "GB234185.TXT", + "hash": "205D28B800A6F59D6E35D0D7B82806A19EC6361B85E18FE825EC5BB83ACB2358", + "fileSize": 1558 + }, + { + "name": "GB0DE20R.TIF", + "hash": "726CE7296C6D48C239A29B0CF32841F0FF8806F2F0BFC907A441B5F245F5CF62", + "fileSize": 53552 + }, + { + "name": "GB1B6D06.TIF", + "hash": "60720957999022763F0B91801AAC22B623EB50513445CBF617112338E9FF7F68", + "fileSize": 50232 + }, + { + "name": "GB234226.TXT", + "hash": "C63C7FA1155A060637A18F35A9442DA378FD906757DC94748E8E8E220FA94E15", + "fileSize": 659 + }, + { + "name": "GB214767.TXT", + "hash": "6B2F8AFE63C6BF387C8306E7BCE406D1C5EBE48013D1B7F84E630013F32CED78", + "fileSize": 725 + }, + { + "name": "GB0DB81I.TIF", + "hash": "6D1357D82737FF54E50D0F2969A9563013BBDA0ACDA239B25B3414F04C1725EB", + "fileSize": 53960 + }, + { + "name": "GB15BB0P.TIF", + "hash": "8C6C46D8BBA04871257BB49C0CC22486DC8E80A52DBF651FAA55D8C5CF17504C", + "fileSize": 27896 + }, + { + "name": "GB0D6A08.TIF", + "hash": "E0553E783E9792CF846E057DF1B0929A2C48F97BE7630E0DAC2D031C4BA5376D", + "fileSize": 22344 + }, + { + "name": "GB0BF70W.TIF", + "hash": "C3C98F71C75EF26B33C50D3EA31CD6E8DFDC85D53683F6184FF4713128B0C91A", + "fileSize": 23264 + }, + { + "name": "GB214687.TXT", + "hash": "0E8726C6DED0B38EEB32F6EC129C84C3E93C5969EA6A148842AF4773601F2F33", + "fileSize": 559 + }, + { + "name": "GB234239.TXT", + "hash": "217E901FA957377446E171359B49F42D07C71A1AAECDDDD24756867F43036C79", + "fileSize": 525 + }, + { + "name": "GB08CE0K.TIF", + "hash": "9F63D189544C8E72CFEB8344E2D2076FD44734142BDA8EC987407189CAA3D009", + "fileSize": 29504 + }, + { + "name": "GB02882T.TIF", + "hash": "9E102B737F6A383CFD0A64DF6F9C100A3A3104C1480D48F2FDBA8EB6E8702865", + "fileSize": 153846 + }, + { + "name": "GB02BC02.TIF", + "hash": "7904779787F8569A12654B3907778010D6D638D36483400067CA27FF4C9DDB93", + "fileSize": 39752 + }, + { + "name": "GB234268.TXT", + "hash": "5E09198E9A0EE964F3D8B3D0892C51C7E731E2DBD4DAA7FF63D4D174EEF81084", + "fileSize": 593 + }, + { + "name": "GB170D0K.TIF", + "hash": "B7A16D00BC5301B6031DFC17CF783F6D31C4782C5BF7FF8A04830321720B0DB7", + "fileSize": 36524 + }, + { + "name": "GB20D50K.TIF", + "hash": "A4FEB10D9FDA56B9DDD35EF61988B2A7D0029F3A800615AF60EB3A8812C001E4", + "fileSize": 136096 + }, + { + "name": "GB02882U.TIF", + "hash": "735F59969E7D4AE581FB405525804A604C3E61162BC7A3192236F2110CD4F38B", + "fileSize": 211832 + }, + { + "name": "GB02DF02.TIF", + "hash": "664E0EDEB6771C75F5792BA51797FD4D394924B827999D08FCDFDA4CE3D0B66A", + "fileSize": 75444 + }, + { + "name": "GB234355.TXT", + "hash": "1CA524D72BADDDF8249A33BCD3839CF237C7117464EC116BD3ACFB2BBB10B900", + "fileSize": 790 + }, + { + "name": "GB13890M.TIF", + "hash": "1B242B32E1302F45ABB5CBC069A38F2E1FB0B591E24F0CEADC5B8EF41057790A", + "fileSize": 97676 + }, + { + "name": "GB0F9C0E.TIF", + "hash": "CA84127FF7980A13F3930C0A8C599897055B4D4C5C15E7B9446F43A3BA3E03FB", + "fileSize": 23324 + }, + { + "name": "GB234341.TXT", + "hash": "47B048F1D3CC4EBAA4EF6416AF278594EE669EDE8E3BE7CD70C4AB8CA0D180DD", + "fileSize": 844 + }, + { + "name": "GB0CDE0I.TIF", + "hash": "298A73931C6E11C55F4A30248345164B451B0D31C44DC124FE635BD6FB89E805", + "fileSize": 28260 + }, + { + "name": "GB0EE915.TIF", + "hash": "361451073F7CB387483BF28EB5693BC670D3A6034075A0FF9D578EA43EE73228", + "fileSize": 42320 + }, + { + "name": "GB234393.TXT", + "hash": "4BC76C27056DEFDA0DA023D8DCDF32A9116BEEA37580C846D3EEA9D6EDC498A6", + "fileSize": 534 + }, + { + "name": "GB17110M.TIF", + "hash": "6EA25BE44EF59E14710FF26145CBAF5E326A1962FA73C40DA90887C6ECD667F0", + "fileSize": 50780 + }, + { + "name": "GB0F8E58.TIF", + "hash": "2480644E8220DC3B3191122AD7827F6E411967D25C6B176103E688580335BC24", + "fileSize": 161462 + }, + { + "name": "GB0C0501.TIF", + "hash": "AD74E96FE04FA9C6F770B36FD4A6DCC0DC7348035A37A337146EDE5DBDF8CF73", + "fileSize": 30976 + }, + { + "name": "GB0F8306.TIF", + "hash": "D13E2EC366CF3EC96C47AB8D5C4500D3E82A4BA3DA5C64BCE4A7C1ABD7DCE867", + "fileSize": 62196 + }, + { + "name": "GB234556.TXT", + "hash": "188F5FD6AF4161BB84BDBBA0CCEE4C7111F79C5F326FE5A368D22B1E6A9CB7AC", + "fileSize": 767 + }, + { + "name": "GB11F317.TIF", + "hash": "339A8E5A3D632E8436E7981ACDA1FFE7987109A2487C341E146EE9E2DFED7B1B", + "fileSize": 20152 + }, + { + "name": "GB0F8E59.TIF", + "hash": "4F27614EE2B66925EDE68DDD5399447695C89FC4D4F399B47CA85FD1A8C78B3D", + "fileSize": 132658 + }, + { + "name": "GB23490O.TIF", + "hash": "ADD60220C4B1EC1326C7FDB7B65849F65001EAF3DAF91F5509371D08141B7057", + "fileSize": 162960 + }, + { + "name": "GB02BC03.TIF", + "hash": "18A95320E95355CA4243773BEB1CFAD02F7CDFD5440719474FB674C7DF58697E", + "fileSize": 38296 + }, + { + "name": "GB14520Q.TIF", + "hash": "9551B412354B9C18C3F682F89460B8DB6C401AEC97AC89CC571FC516F059D767", + "fileSize": 37140 + }, + { + "name": "GB234665.TXT", + "hash": "C55BD153DD9B0D57AB9A3283BBED642495C0021D44E6539269D6C6195A878798", + "fileSize": 465 + }, + { + "name": "GB0F8E5A.TIF", + "hash": "53B968724EE885234620625BBE0AB18BBC7EDF2660DB128074387D1D6B4411DB", + "fileSize": 156434 + }, + { + "name": "GB234695.TXT", + "hash": "A4B4CA54523496D07EFBB53586770CF5E7770FC51DA7EDBE5B2BB267A949C02D", + "fileSize": 4117 + }, + { + "name": "GB0F8E5B.TIF", + "hash": "EE956352226B11019DA97378E41C2DC06170EDF7679A6A0756293390919742EA", + "fileSize": 100168 + }, + { + "name": "GB234714.TXT", + "hash": "0248DF342986B2BD03334A8230B3EE9796829A34EBA67E78E1F58590AFFED973", + "fileSize": 738 + }, + { + "name": "GB0BE70B.TIF", + "hash": "43E01D66DAD6B2D819D0A2F4B655F5A69E78F4FDD60BEAD819DD314AF03F7570", + "fileSize": 93582 + }, + { + "name": "GB0F8E5C.TIF", + "hash": "75EE7F182AE0BF2F32BFDFEFA2272BAF04548EEC1FF84297FB8AB3354BECD9A3", + "fileSize": 129236 + }, + { + "name": "GB13A801.TIF", + "hash": "43CCA2FF2C6A53BF42731BCD3FEA7DDB40A368440A85406D3BEC33FC18244B79", + "fileSize": 48788 + }, + { + "name": "GB1BB803.TIF", + "hash": "8E80A21017F194856A63FCE937B55778DA69D25A1C8D5EFFBE0850C288B3BC30", + "fileSize": 25332 + }, + { + "name": "GB224054.TXT", + "hash": "F703D10214D1A1546DD39BC59DDB4FDA6C8CFA9BE1F00DA8EAB6726115650970", + "fileSize": 482 + }, + { + "name": "GB272E0B.TIF", + "hash": "117A15F58EFD548A9B0BB6EE8393F7F1ED474D78BC0F6E59D9B6835CBB394C56", + "fileSize": 42662 + }, + { + "name": "GB050D03.TIF", + "hash": "CE832C58C794A2AB7523675E89E8F05222827FA7B5D884D7996480B2CDBFE0A3", + "fileSize": 32140 + }, + { + "name": "GB0DA90F.TIF", + "hash": "1A00275A8B9876F0121F045ACC452DD66DE22194737038A5F2930022FACE05B9", + "fileSize": 35532 + }, + { + "name": "GB26233L.TIF", + "hash": "923C5DBA55F010D388A22FC1D61E81C47906A84FBBEB4EABD355A6E1981E3425", + "fileSize": 221822 + }, + { + "name": "GB16930I.TIF", + "hash": "7D7AAE6B4EA0400A03F398D41BC9B53E0B9DBEF3D117B62482C75F243A3B0A77", + "fileSize": 50380 + }, + { + "name": "GB26233M.TIF", + "hash": "269BC8BB26C3A0D6302568694AE0981C99F83A6D5335CBDABD7228384C84B81E", + "fileSize": 362052 + }, + { + "name": "GB0BAB24.TIF", + "hash": "55E8CEEFADF053A2AAB5D4641D80809CBCC22A664B961F05FA2283FF6420AE51", + "fileSize": 25824 + }, + { + "name": "GB178D09.TIF", + "hash": "FE212E5869964D88076A0A8D1283713CF1ABE42FD4BCB726978DEF478A483074", + "fileSize": 48864 + }, + { + "name": "GB26233N.TIF", + "hash": "CF1EDDAE4818AD1C758C45CCCA6516B44BB90456E291253561D7240B2B370EF2", + "fileSize": 360964 + }, + { + "name": "GB26233O.TIF", + "hash": "9461484ACE670AEC056FCB3BAF78C177E1111C3C53D513188D26DD8301FE9941", + "fileSize": 262616 + }, + { + "name": "GB15E44Q.TIF", + "hash": "5CBA582CD3A2E11B7A0A444938C645F5501403EA5637B41280946CC9A66C29A3", + "fileSize": 114920 + }, + { + "name": "GB267A01.TIF", + "hash": "A6D467D77C8956B52A252955F8993115707974C282AABDBD8F57EEA4C2CE41FF", + "fileSize": 143494 + }, + { + "name": "GB248B06.TIF", + "hash": "6FB45E4757328CC590650CD9EC93AA33CF53163AACB6E5DAC6493777B2D24E91", + "fileSize": 97246 + }, + { + "name": "GB248C0G.TIF", + "hash": "4B9B43C02BB99B094EE73E7D492075411DE927D7DEB5B46511BA759E9E8FF56F", + "fileSize": 92040 + }, + { + "name": "GB0C0603.TIF", + "hash": "F994F6820AB60598B849E31A4FCF0D16E7F533C5B18CB3E91BE16E079B45C34D", + "fileSize": 22052 + }, + { + "name": "GB262342.TIF", + "hash": "6B3B9561E54EEE965AC3F715E378F01142437293F2326B58E0BF14BCABE69233", + "fileSize": 462846 + }, + { + "name": "GB0C0601.TIF", + "hash": "80454EB9B988F9C7225076303B6A7225DD72DE2AF339E9E2F96AF53B4FAA695E", + "fileSize": 22784 + }, + { + "name": "GB04850K.TIF", + "hash": "703E0A6F8795FF91B89BBC2823808AFE1E1B1FDB07749BB18ED5AAB813D11850", + "fileSize": 15288 + }, + { + "name": "GB25F30C.TIF", + "hash": "77C1A6F8B973FFE2909BC84ED300F83A2DCB97A3A5BA96E3FB9AFDFD75492476", + "fileSize": 211028 + }, + { + "name": "GB25F30D.TIF", + "hash": "2BB981E0A18FFDD0F61BEF628FE1BAC611B88335CBBB1EED1CD59069B559D11D", + "fileSize": 237204 + }, + { + "name": "GB0BF208.TIF", + "hash": "57C81D9A930B6D85C4C8A7ACA8EDBA59740E07B196D33C019E4AE1F53F6A7BBB", + "fileSize": 25700 + }, + { + "name": "GB1050PH.TIF", + "hash": "66E90EC21DBDD2D73D7AEE7C8C1690FF58075B3E091EB86E5DD413F575949C06", + "fileSize": 461104 + }, + { + "name": "GB16930S.TIF", + "hash": "5B933C33B151ABCC1FFE11FE905AE3AFC793F837D26862A0669DF4DF5FA22968", + "fileSize": 46964 + }, + { + "name": "GB219008.TIF", + "hash": "D7A91D97949C53AE2B9413A5FF60A013282D559EF83C240D30E382796FFF6182", + "fileSize": 146242 + }, + { + "name": "GB219009.TIF", + "hash": "BF3D577798B9555ED24A875E9C31006557B9B35D5EF3A9758537752327E1CD08", + "fileSize": 249318 + }, + { + "name": "GB0F970J.TIF", + "hash": "403CE05FDA2419D4BB9155810D179624FB5FC162080B6A8CE8C3C0F577C34F09", + "fileSize": 56796 + }, + { + "name": "GB223384.TXT", + "hash": "E4AE8D5D32DF1DE96EAF59C1D349A61F83544AA3FA2C3CDEC90E208896A56635", + "fileSize": 973 + }, + { + "name": "GB201096.TXT", + "hash": "EC93458B15A3C1655C53EC73088B68A7ACD64854F4C007EEC727CC1892D01157", + "fileSize": 882 + }, + { + "name": "GB223380.TXT", + "hash": "50ADD8EFC5BC1F15AB31C3B6D89AF6B1C79B3BB0821FF3A430F9445F40C8BD23", + "fileSize": 569 + }, + { + "name": "GB621116.TXT", + "hash": "501BB9A9834B3C445C361762B6608B65B0DD4250DD047C3049B938AF47FB781B", + "fileSize": 930 + }, + { + "name": "GB223462.TXT", + "hash": "DA4272B151C4AD2DE63138138F533D181270347C678F4D3AEB32F6AC3D2D94BE", + "fileSize": 873 + }, + { + "name": "GB196488.TXT", + "hash": "BD8DB9898B13F0BFA602D52912A87EC14462A7E411462A0CD97DC291F2D26B3C", + "fileSize": 1543 + }, + { + "name": "GB223656.TXT", + "hash": "7AC4308D5D22116CA74EDCB2CC18B9945B0A0F3C7250EDEE2AAD0305F37072D6", + "fileSize": 472 + }, + { + "name": "GB223632.TXT", + "hash": "9F8C35F541085AB7073B34249D1FF4710397A4ED85E57F72BC6A1909F77AED5D", + "fileSize": 558 + }, + { + "name": "GB223807.TXT", + "hash": "60384524D301327D9A970E7BB60ACF61B1A9804A18462545BA1B7E60A1FC000C", + "fileSize": 6238 + }, + { + "name": "GB262337.TIF", + "hash": "E627772D515DA209DBBD287D01536ECC34F0CFF36F60099B5A296E0CB4CCF0A2", + "fileSize": 304578 + }, + { + "name": "GB262338.TIF", + "hash": "C946E03B38D0101FFCDEF5CDA332733D6C8365C200D7C5FBB9DE607D6E26E57A", + "fileSize": 283278 + }, + { + "name": "GB262339.TIF", + "hash": "5F1E92029A381C12A235274FA980365F359724CBB302A24EF3B1A4C91517378D", + "fileSize": 117672 + }, + { + "name": "GB26233A.TIF", + "hash": "C5DEE3FFCB6041ADD754C0A7DB71CA87FA7CF16FAF278B61D9D944FD4B714A7F", + "fileSize": 230666 + }, + { + "name": "GB0F8307.TIF", + "hash": "3A0119F33718DAE1FE980B026C26D964693FB387818AC7F6B5E9988088301265", + "fileSize": 158070 + }, + { + "name": "GB26233C.TIF", + "hash": "A6E2C1C3BD2A812F66144AFEE1FC1F144A5B336CC57D1013A4DFDD19C9C34E28", + "fileSize": 113742 + }, + { + "name": "GB26233D.TIF", + "hash": "2DEDB1835A5D2E0F1957F1B6217D67FE7D93D184D8478F127B88D435FEB65075", + "fileSize": 516230 + }, + { + "name": "GB101119.TIF", + "hash": "71CAF0ED33CC19C5933297ADE730B747F9E4F7591444AF439D2FC59B0A0C641A", + "fileSize": 51936 + }, + { + "name": "GB26233E.TIF", + "hash": "F7E9F1CF16958D26103038D608687F74C78B1CCF401AF097C28B447E9EE09943", + "fileSize": 379502 + }, + { + "name": "GB11BA0N.TIF", + "hash": "F9096EEBA03A1CDAD1DDC5912A1CDA89CDDAE2A2DA604E03C2A15F781154750A", + "fileSize": 14588 + }, + { + "name": "GB223852.TXT", + "hash": "9CC369EF7288EB1B47A14C66067E6C3CFCA1F54A393F484561E7440216804B45", + "fileSize": 550 + }, + { + "name": "GB26233F.TIF", + "hash": "8DC7CCCC6E8DE439D0A50CE0F15F62A76BC10231BE4DC53C9DEA8118415713B8", + "fileSize": 387036 + }, + { + "name": "GB12B603.TIF", + "hash": "83A70E72FC32B6CB045EC71BEB835A587A31CB8B6563B9B758C06E4906490C15", + "fileSize": 44232 + }, + { + "name": "GB223924.TXT", + "hash": "EE8E0133956108AE19A9E3A935AFDC7241FD1CA7E1F3BB2D8130D8C42EB8C9B0", + "fileSize": 759 + }, + { + "name": "GB26233G.TIF", + "hash": "A1BD3CA56B3421C72C173D718748123653777FEA36E7E930C02C8B0153F0AB59", + "fileSize": 383114 + }, + { + "name": "GB0BAA5I.TIF", + "hash": "AA9811A57B39323FE393DECB94877E838AE7D89455E96648AB0E65A40272788B", + "fileSize": 77602 + }, + { + "name": "GB02B60H.TIF", + "hash": "C3B4C90E2D62D9021094D15F33DB078CED337BC61AB045B7C5960A1F1A2822C5", + "fileSize": 29004 + }, + { + "name": "GB223907.TXT", + "hash": "39E89072A7DCA2110781A3F61F72BAF18E67D77C11D1565144C35F3D48DD5312", + "fileSize": 1023 + }, + { + "name": "GB0BF203.TIF", + "hash": "620954E25DEA9B1814AFFA4BC9868DB50EFF737513C97499AE232D5D93CB7F18", + "fileSize": 30704 + }, + { + "name": "GB223935.TXT", + "hash": "63266A91708CEB2EC66B1FDD5752C70E77FFF45AD9125A0FA74DDB04C6B3DE04", + "fileSize": 9117 + }, + { + "name": "GB223935.TIF", + "hash": "F1F085AC531E1DC00F9DA2D3BEF7A139333F33E69E2E829C9AF551607B7110D0", + "fileSize": 100424 + } + ] + } + ], + "unitsOfSale": [] + } +} diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadePayloadTestData/AIOUpdateCell.JSON b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadePayloadTestData/AIOUpdateCell.JSON new file mode 100644 index 00000000..8ff8ebd3 --- /dev/null +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/ERPFacadePayloadTestData/AIOUpdateCell.JSON @@ -0,0 +1,87 @@ +{ + "specversion": "1.0", + "type": "uk.gov.ukho.encpublishing.enccontentpublished.v2.2", + "source": "https://encpublishing.ukho.gov.uk", + "id": "be05a29f-d7af-49d4-87b3-fea74e43fafb", + "time": "2024-10-11T14:01:07.2158718+00:00", + "subject": "GB800001", + "datacontenttype": "application/json", + "data": { + "correlationId": "52323b16-ed68-4adb-2838-08dce9f35151", + "ukhoWeekNumber": { + "year": 2024, + "week": 28, + "currentWeekAlphaCorrection": false + }, + "products": [ + { + "dataSetName": "GB800001.001", + "productName": "GB800001", + "title": "Admiralty Information Overlay", + "scale": 1, + "usageBand": 8, + "editionNumber": 32, + "updateNumber": 1, + "mayAffectHoldings": false, + "contentChange": true, + "permit": "ThisWillBeReplacedWithActualPermitFromKeyvault", + "providerCode": "11", + "providerName": "VAR Unique", + "size": "large", + "bundle": [ + { + "bundleType": "DVD", + "location": "M1;B3" + } + ], + "status": { + "statusName": "Update", + "statusDate": "2024-01-18", + "isNewCell": false + }, + "replaces": [], + "replacedBy": [], + "additionalCoverage": [], + "geographicLimit": { + "boundingBox": { + "northLimit": 90, + "southLimit": -90, + "eastLimit": -180, + "westLimit": 180 + } + }, + "inUnitsOfSale": [], + "s63": { + "name": "GB800001.001", + "hash": "E99CD7B0B0C60709D9A70BF0CCDC2712403824B50111E6242E7D91753365D6AA", + "fileSize": 12048, + "compression": true, + "s57Crc": "E4BADE1C" + }, + "signature": { + "name": "GBP00001.001", + "hash": "2BD7095738E9455F523B99D35AD28588974BFF3EE3B4B04C65B9915E56C8CA7A", + "fileSize": 874 + }, + "ancillaryFiles": [ + { + "name": "GBNOOVER.TXT", + "hash": "44460F8B9586E7D5FD838F758BD7247B568706B4704E6BFC48217EB454049378", + "fileSize": 317 + }, + { + "name": "GB240266.TXT", + "hash": "D94CF73BCD9F2EB3107C5A9B3B165A5B8970CFEE1EE547122A8D9DFD08BB0369", + "fileSize": 1328 + }, + { + "name": "GB240260.TXT", + "hash": "2F8675A364DB96C660CDC3E0230496B56491459B17D69FD8F04940A9FF704ABD", + "fileSize": 499 + } + ] + } + ], + "unitsOfSale": [] + } +} diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/WebhookScenarios.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/WebhookScenarios.cs index ed6aaa79..d5986d37 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/WebhookScenarios.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/FunctionalTests/WebhookScenarios.cs @@ -101,6 +101,10 @@ public async Task WhenValidEventInNewEncContentPublishedEventReceivedWithTokenHa //Re-issue scenario [TestCase("Re-issue.JSON", "PermitWithSameKey", TestName = "WhenICallTheWebhookWithReIssueScenario_ThenWebhookReturns200Response")] + //AIO-cell scenarios + [TestCase("AIOUpdateCell.JSON", "PermitWithSameKey", TestName = "WhenICallTheWebhookWithAIOUpdateCellScenario_ThenWebhookReturns200Response")] + [TestCase("AIONewCell.JSON", "PermitWithSameKey", TestName = "WhenICallTheWebhookWithAIONewCellScenario_ThenWebhookReturns200Response")] + public async Task WhenValidEventInNewEncContentPublishedEventReceivedWithValidToken_ThenWebhookReturns200OkResponse(string payloadJsonFileName, string permitState) { Console.WriteLine("Scenario:" + payloadJsonFileName + "\n"); diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/Service/S57WebhookEndpoint.cs b/tests/UKHO.ERPFacade.API.FunctionalTests/Service/S57WebhookEndpoint.cs index fbc14e5d..8d468892 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/Service/S57WebhookEndpoint.cs +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/Service/S57WebhookEndpoint.cs @@ -75,6 +75,11 @@ public async Task PostWebhookResponseAsyncForXml(string filePath, //Logic to download XML from container using TraceID from JSON string generatedXmlFilePath = _azureBlobStorageHelper.DownloadGeneratedXmlFile(generatedXmlFolder, correlationId, Constants.S57EventContainerName); + if (filePath.Contains(Constants.AioKey) && generatedXmlFilePath.Length == 0) + { + return response; + } + //Expected XML string xmlFilePath = filePath.Replace(Config.TestConfig.PayloadFolder, Constants.ErpFacadeExpectedXmlFiles).Replace(".JSON", ".xml"); diff --git a/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj b/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj index 791e5621..279ee9a5 100644 --- a/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj +++ b/tests/UKHO.ERPFacade.API.FunctionalTests/UKHO.ERPFacade.API.FunctionalTests.csproj @@ -156,6 +156,12 @@ Always + + Always + + + Always + Always diff --git a/tests/UKHO.ERPFacade.API.UnitTests/Controllers/WebhookControllerTests.cs b/tests/UKHO.ERPFacade.API.UnitTests/Controllers/WebhookControllerTests.cs index b87af107..4e3d41e2 100644 --- a/tests/UKHO.ERPFacade.API.UnitTests/Controllers/WebhookControllerTests.cs +++ b/tests/UKHO.ERPFacade.API.UnitTests/Controllers/WebhookControllerTests.cs @@ -16,6 +16,7 @@ using NUnit.Framework; using UKHO.ERPFacade.API.Controllers; using UKHO.ERPFacade.API.Helpers; +using UKHO.ERPFacade.API.Services; using UKHO.ERPFacade.Common.Configuration; using UKHO.ERPFacade.Common.Exceptions; using UKHO.ERPFacade.Common.HttpClients; @@ -36,7 +37,7 @@ public class WebhookControllerTests private IAzureQueueHelper _fakeAzureQueueHelper; private ISapClient _fakeSapClient; private IXmlHelper _fakeXmlHelper; - private IEncContentSapMessageBuilder _fakeEncContentSapMessageBuilder; + private IS57Service _fakeS57Service; private IOptions _fakeSapConfig; private WebhookController _fakeWebHookController; private ILicenceUpdatedSapMessageBuilder _fakeLicenceUpdatedSapMessageBuilder; @@ -51,7 +52,7 @@ public void Setup() _fakeAzureQueueHelper = A.Fake(); _fakeSapClient = A.Fake(); _fakeXmlHelper = A.Fake(); - _fakeEncContentSapMessageBuilder = A.Fake(); + _fakeS57Service = A.Fake(); _fakeLicenceUpdatedSapMessageBuilder = A.Fake(); _fakeSapConfig = Options.Create(new SapConfiguration() { @@ -64,7 +65,7 @@ public void Setup() _fakeAzureBlobEventWriter, _fakeAzureQueueHelper, _fakeSapClient, - _fakeEncContentSapMessageBuilder, + _fakeS57Service, _fakeSapConfig, _fakeLicenceUpdatedSapMessageBuilder); } @@ -115,10 +116,7 @@ public async Task WhenValidEventInNewEncContentPublishedEventReceived_ThenWebhoo var result = (OkObjectResult)await _fakeWebHookController.NewEncContentPublishedEventReceived(fakeEncEventJson); - A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateEntity(A.Ignored, A.Ignored, A[]>.Ignored)).MustHaveHappened(); - A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(2, Times.Exactly); - A.CallTo(() => _fakeSapClient.PostEventData(A.Ignored, A.Ignored, A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeS57Service.ProcessS57Event(A.Ignored)).MustHaveHappened(); result.StatusCode.Should().Be(200); @@ -126,36 +124,6 @@ public async Task WhenValidEventInNewEncContentPublishedEventReceived_ThenWebhoo && call.GetArgument(0) == LogLevel.Information && call.GetArgument(1) == EventIds.NewEncContentPublishedEventReceived.ToEventId() && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "ERP Facade webhook has received new enccontentpublished event from EES.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.AddingEntryForEncContentPublishedEventInAzureTable.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Adding/Updating entry for enccontentpublished event in azure table.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.UploadEncContentPublishedEventInAzureBlobStarted.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Uploading enccontentpublished event payload in blob storage.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.UploadEncContentPublishedEventInAzureBlobCompleted.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "The enccontentpublished event payload is uploaded in blob storage successfully.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.UploadSapXmlPayloadInAzureBlobStarted.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Uploading the SAP XML payload in blob storage.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.UploadSapXmlPayloadInAzureBlobCompleted.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "SAP XML payload is uploaded in blob storage successfully.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.EncUpdateSentToSap.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "ENC update has been sent to SAP successfully. | {StatusCode}").MustHaveHappenedOnceExactly(); } [Test] @@ -182,57 +150,6 @@ public async Task WhenCorrelationIdIsMissingInNewEncContentPublishedEvent_ThenWe && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "CorrelationId is missing in enccontentpublished event.").MustHaveHappenedOnceExactly(); } - [Test] - public void WhenSapDoesNotRespond200Ok_ThenWebhookReturns500InternalServerResponse() - { - XmlDocument xmlDocument = new(); - - var fakeEncEventJson = JObject.Parse(@"{""data"":{""correlationId"":""123""}}"); - - A.CallTo(() => _fakeXmlHelper.CreateXmlDocument(A.Ignored)).Returns(xmlDocument); - A.CallTo(() => _fakeSapClient.PostEventData(A.Ignored, A.Ignored, A.Ignored, A.Ignored, A.Ignored)) - .Returns(new HttpResponseMessage() - { - StatusCode = HttpStatusCode.Unauthorized - }); - - Assert.ThrowsAsync(() => _fakeWebHookController.NewEncContentPublishedEventReceived(fakeEncEventJson)); - - A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened(); - A.CallTo(() => _fakeAzureTableReaderWriter.UpdateEntity(A.Ignored, A.Ignored, A[]>.Ignored)).MustNotHaveHappened(); - A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.NewEncContentPublishedEventReceived.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "ERP Facade webhook has received new enccontentpublished event from EES.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.AddingEntryForEncContentPublishedEventInAzureTable.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Adding/Updating entry for enccontentpublished event in azure table.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.UploadEncContentPublishedEventInAzureBlobStarted.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Uploading enccontentpublished event payload in blob storage.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.UploadEncContentPublishedEventInAzureBlobCompleted.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "The enccontentpublished event payload is uploaded in blob storage successfully.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.UploadSapXmlPayloadInAzureBlobStarted.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Uploading the SAP XML payload in blob storage.").MustHaveHappenedOnceExactly(); - - A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" - && call.GetArgument(0) == LogLevel.Information - && call.GetArgument(1) == EventIds.UploadSapXmlPayloadInAzureBlobCompleted.ToEventId() - && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "SAP XML payload is uploaded in blob storage successfully.").MustHaveHappenedOnceExactly(); - } - [Test] public void Does_Constructor_Throws_ArgumentNullException_When_Paramter_Is_Null() { @@ -243,7 +160,7 @@ public void Does_Constructor_Throws_ArgumentNullException_When_Paramter_Is_Null( _fakeAzureBlobEventWriter, _fakeAzureQueueHelper, _fakeSapClient, - _fakeEncContentSapMessageBuilder, + _fakeS57Service, null, _fakeLicenceUpdatedSapMessageBuilder)) .ParamName diff --git a/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewAIOCell.JSON b/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewAIOCell.JSON new file mode 100644 index 00000000..d04a477e --- /dev/null +++ b/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewAIOCell.JSON @@ -0,0 +1,82 @@ +{ + "specversion": "1.0", + "type": "uk.gov.ukho.encpublishing.enccontentpublished.v2.2", + "source": "https://encpublishing.ukho.gov.uk", + "id": "47c82948-f389-41bb-a77c-bdd3f8c306d7", + "time": "2024-10-11T12:54:30.6083284+00:00", + "subject": "GB800001", + "datacontenttype": "application/json", + "data": { + "correlationId": "19cc417e-c2a1-438d-2837-08dce9f35151", + "ukhoWeekNumber": { + "year": 2024, + "week": 28, + "currentWeekAlphaCorrection": false + }, + "products": [ + { + "dataSetName": "GB800001.000", + "productName": "GB800001", + "title": "Admiralty Information Overlay", + "scale": 1, + "usageBand": 8, + "editionNumber": 32, + "updateNumber": 0, + "mayAffectHoldings": true, + "contentChange": true, + "permit": "permitString", + "providerCode": "11", + "providerName": "VAR Unique", + "size": "large", + "bundle": [ + { + "bundleType": "DVD", + "location": "M1;B3" + } + ], + "status": { + "statusName": "New Edition", + "statusDate": "2024-01-11", + "isNewCell": true + }, + "replaces": [], + "replacedBy": [], + "additionalCoverage": [], + "geographicLimit": { + "boundingBox": { + "northLimit": 90, + "southLimit": -90, + "eastLimit": -180, + "westLimit": 180 + } + }, + "inUnitsOfSale": [], + "s63": { + "name": "GB800001.000", + "hash": "hash", + "fileSize": 1998768, + "compression": true, + "s57Crc": "DB4A0A77" + }, + "signature": { + "name": "GBP00001.000", + "hash": "hash", + "fileSize": 874 + }, + "ancillaryFiles": [ + { + "name": "GBNOOVER.TXT", + "hash": "hash", + "fileSize": 317 + }, + { + "name": "GB196063.TXT", + "hash": "hash", + "fileSize": 719 + } + ] + } + ], + "unitsOfSale": [] + } +} diff --git a/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithNullYearInUkhoWeekNumberSection.JSON b/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithNullYearInUkhoWeekNumberSection.JSON new file mode 100644 index 00000000..934a8e9f --- /dev/null +++ b/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithNullYearInUkhoWeekNumberSection.JSON @@ -0,0 +1,139 @@ +{ + "specversion": "1.0", + "type": "uk.gov.ukho.encpublishing.enccontentpublished.v2.2", + "source": "https://encpublishing.ukho.gov.uk", + "id": "f206ec1c-0b83-43a2-b11c-cca1d981c2a4", + "time": "2024-09-13T05:34:42.4904747+00:00", + "subject": "US5AK9DI", + "datacontenttype": "application/json", + "data": { + "correlationId": "5004bc72-5beb-42c1-5037-08dcc74c342e", + "ukhoWeekNumber": { + "year": null, + "week": 12, + "currentWeekAlphaCorrection": true + }, + "products": [ + { + "dataSetName": "US5AK9DI.000", + "productName": "US5AK9DI", + "title": "Amlia Island - Svechnikof Harbor", + "scale": 22000, + "usageBand": 5, + "editionNumber": 1, + "updateNumber": 0, + "mayAffectHoldings": true, + "contentChange": true, + "permit": "permitstring", + "providerCode": "1", + "providerName": "ICE", + "size": "medium", + "bundle": [ + { + "bundleType": "DVD", + "location": "M1;B5" + } + ], + "status": { + "statusName": "New Edition", + "statusDate": "2024-07-11", + "isNewCell": true + }, + "replaces": [], + "replacedBy": [], + "additionalCoverage": [], + "geographicLimit": { + "boundingBox": { + "northLimit": 52.125, + "southLimit": 52.05, + "eastLimit": -173.4, + "westLimit": -173.55 + }, + "polygons": [] + }, + "inUnitsOfSale": [ + "PAYSF", + "US5AK9DI" + ], + "s63": { + "name": "US5AK9DI.000", + "hash": "", + "fileSize": 0, + "compression": true, + "s57Crc": "8A46B83F" + }, + "signature": { + "name": "USMAK9DI.000", + "hash": "", + "fileSize": 0 + }, + "ancillaryFiles": [ + { + "name": "US213DIA.TXT", + "hash": "hash", + "fileSize": 4008 + }, + { + "name": "US213DIB.TXT", + "hash": "hash", + "fileSize": 293 + } + ] + } + ], + "unitsOfSale": [ + { + "unitName": "US5AK9DI", + "title": "Amlia Island - Svechnikof Harbor", + "unitOfSaleType": "unit", + "unitSize": "medium", + "unitType": "AVCS Units Harbour", + "providerCode": "1", + "providerName": "ICE", + "status": "ForSale", + "isNewUnitOfSale": true, + "geographicLimit": { + "boundingBox": { + "northLimit": 52.125, + "southLimit": 52.05, + "eastLimit": -173.4, + "westLimit": -173.55 + }, + "polygons": [] + }, + "compositionChanges": { + "addProducts": [ + "US5AK9DI" + ], + "removeProducts": [] + } + }, + { + "unitName": "PAYSF", + "title": "World Folio", + "unitOfSaleType": "folio", + "unitSize": "large", + "unitType": "AVCS Folio Transit", + "providerCode": "1", + "providerName": "ICE", + "status": "ForSale", + "isNewUnitOfSale": false, + "geographicLimit": { + "boundingBox": { + "northLimit": 0, + "southLimit": 0, + "eastLimit": 0, + "westLimit": 0 + }, + "polygons": [] + }, + "compositionChanges": { + "addProducts": [ + "US5AK9DI" + ], + "removeProducts": [] + } + } + ] + } +} diff --git a/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithNullcurrentWeekAlphaCorrectionInUkhoWeekNumberSection.JSON b/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithNullcurrentWeekAlphaCorrectionInUkhoWeekNumberSection.JSON new file mode 100644 index 00000000..0a61419f --- /dev/null +++ b/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithNullcurrentWeekAlphaCorrectionInUkhoWeekNumberSection.JSON @@ -0,0 +1,138 @@ +{ + "specversion": "1.0", + "type": "uk.gov.ukho.encpublishing.enccontentpublished.v2.2", + "source": "https://encpublishing.ukho.gov.uk", + "id": "f206ec1c-0b83-43a2-b11c-cca1d981c2a4", + "time": "2024-09-13T05:34:42.4904747+00:00", + "subject": "US5AK9DI", + "datacontenttype": "application/json", + "data": { + "correlationId": "5004bc72-5beb-42c1-5037-08dcc74c342e", + "ukhoWeekNumber": { + "year": 2024, + "week": 12 + }, + "products": [ + { + "dataSetName": "US5AK9DI.000", + "productName": "US5AK9DI", + "title": "Amlia Island - Svechnikof Harbor", + "scale": 22000, + "usageBand": 5, + "editionNumber": 1, + "updateNumber": 0, + "mayAffectHoldings": true, + "contentChange": true, + "permit": "permitstring", + "providerCode": "1", + "providerName": "ICE", + "size": "medium", + "bundle": [ + { + "bundleType": "DVD", + "location": "M1;B5" + } + ], + "status": { + "statusName": "New Edition", + "statusDate": "2024-07-11", + "isNewCell": true + }, + "replaces": [], + "replacedBy": [], + "additionalCoverage": [], + "geographicLimit": { + "boundingBox": { + "northLimit": 52.125, + "southLimit": 52.05, + "eastLimit": -173.4, + "westLimit": -173.55 + }, + "polygons": [] + }, + "inUnitsOfSale": [ + "PAYSF", + "US5AK9DI" + ], + "s63": { + "name": "US5AK9DI.000", + "hash": "", + "fileSize": 0, + "compression": true, + "s57Crc": "8A46B83F" + }, + "signature": { + "name": "USMAK9DI.000", + "hash": "", + "fileSize": 0 + }, + "ancillaryFiles": [ + { + "name": "US213DIA.TXT", + "hash": "hash", + "fileSize": 4008 + }, + { + "name": "US213DIB.TXT", + "hash": "hash", + "fileSize": 293 + } + ] + } + ], + "unitsOfSale": [ + { + "unitName": "US5AK9DI", + "title": "Amlia Island - Svechnikof Harbor", + "unitOfSaleType": "unit", + "unitSize": "medium", + "unitType": "AVCS Units Harbour", + "providerCode": "1", + "providerName": "ICE", + "status": "ForSale", + "isNewUnitOfSale": true, + "geographicLimit": { + "boundingBox": { + "northLimit": 52.125, + "southLimit": 52.05, + "eastLimit": -173.4, + "westLimit": -173.55 + }, + "polygons": [] + }, + "compositionChanges": { + "addProducts": [ + "US5AK9DI" + ], + "removeProducts": [] + } + }, + { + "unitName": "PAYSF", + "title": "World Folio", + "unitOfSaleType": "folio", + "unitSize": "large", + "unitType": "AVCS Folio Transit", + "providerCode": "1", + "providerName": "ICE", + "status": "ForSale", + "isNewUnitOfSale": false, + "geographicLimit": { + "boundingBox": { + "northLimit": 0, + "southLimit": 0, + "eastLimit": 0, + "westLimit": 0 + }, + "polygons": [] + }, + "compositionChanges": { + "addProducts": [ + "US5AK9DI" + ], + "removeProducts": [] + } + } + ] + } +} diff --git a/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithoutYearInUkhoWeekNumberSection.JSON b/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithoutYearInUkhoWeekNumberSection.JSON new file mode 100644 index 00000000..9aa7a633 --- /dev/null +++ b/tests/UKHO.ERPFacade.API.UnitTests/ERPTestData/NewCellWithoutYearInUkhoWeekNumberSection.JSON @@ -0,0 +1,138 @@ +{ + "specversion": "1.0", + "type": "uk.gov.ukho.encpublishing.enccontentpublished.v2.2", + "source": "https://encpublishing.ukho.gov.uk", + "id": "f206ec1c-0b83-43a2-b11c-cca1d981c2a4", + "time": "2024-09-13T05:34:42.4904747+00:00", + "subject": "US5AK9DI", + "datacontenttype": "application/json", + "data": { + "correlationId": "5004bc72-5beb-42c1-5037-08dcc74c342e", + "ukhoWeekNumber": { + "week": 12, + "currentWeekAlphaCorrection": true + }, + "products": [ + { + "dataSetName": "US5AK9DI.000", + "productName": "US5AK9DI", + "title": "Amlia Island - Svechnikof Harbor", + "scale": 22000, + "usageBand": 5, + "editionNumber": 1, + "updateNumber": 0, + "mayAffectHoldings": true, + "contentChange": true, + "permit": "permitstring", + "providerCode": "1", + "providerName": "ICE", + "size": "medium", + "bundle": [ + { + "bundleType": "DVD", + "location": "M1;B5" + } + ], + "status": { + "statusName": "New Edition", + "statusDate": "2024-07-11", + "isNewCell": true + }, + "replaces": [], + "replacedBy": [], + "additionalCoverage": [], + "geographicLimit": { + "boundingBox": { + "northLimit": 52.125, + "southLimit": 52.05, + "eastLimit": -173.4, + "westLimit": -173.55 + }, + "polygons": [] + }, + "inUnitsOfSale": [ + "PAYSF", + "US5AK9DI" + ], + "s63": { + "name": "US5AK9DI.000", + "hash": "", + "fileSize": 0, + "compression": true, + "s57Crc": "8A46B83F" + }, + "signature": { + "name": "USMAK9DI.000", + "hash": "", + "fileSize": 0 + }, + "ancillaryFiles": [ + { + "name": "US213DIA.TXT", + "hash": "hash", + "fileSize": 4008 + }, + { + "name": "US213DIB.TXT", + "hash": "hash", + "fileSize": 293 + } + ] + } + ], + "unitsOfSale": [ + { + "unitName": "US5AK9DI", + "title": "Amlia Island - Svechnikof Harbor", + "unitOfSaleType": "unit", + "unitSize": "medium", + "unitType": "AVCS Units Harbour", + "providerCode": "1", + "providerName": "ICE", + "status": "ForSale", + "isNewUnitOfSale": true, + "geographicLimit": { + "boundingBox": { + "northLimit": 52.125, + "southLimit": 52.05, + "eastLimit": -173.4, + "westLimit": -173.55 + }, + "polygons": [] + }, + "compositionChanges": { + "addProducts": [ + "US5AK9DI" + ], + "removeProducts": [] + } + }, + { + "unitName": "PAYSF", + "title": "World Folio", + "unitOfSaleType": "folio", + "unitSize": "large", + "unitType": "AVCS Folio Transit", + "providerCode": "1", + "providerName": "ICE", + "status": "ForSale", + "isNewUnitOfSale": false, + "geographicLimit": { + "boundingBox": { + "northLimit": 0, + "southLimit": 0, + "eastLimit": 0, + "westLimit": 0 + }, + "polygons": [] + }, + "compositionChanges": { + "addProducts": [ + "US5AK9DI" + ], + "removeProducts": [] + } + } + ] + } +} diff --git a/tests/UKHO.ERPFacade.API.UnitTests/Helpers/EncContentSapMessageBuilderTests.cs b/tests/UKHO.ERPFacade.API.UnitTests/Helpers/EncContentSapMessageBuilderTests.cs index 758f4752..73bddeef 100644 --- a/tests/UKHO.ERPFacade.API.UnitTests/Helpers/EncContentSapMessageBuilderTests.cs +++ b/tests/UKHO.ERPFacade.API.UnitTests/Helpers/EncContentSapMessageBuilderTests.cs @@ -75,12 +75,14 @@ public void WhenBuildSapMessageXmlIsCalledWithCancelCellWithExistingCellReplacem { var cancelReplaceCellEventPayloadJson = TestHelper.ReadFileData("ERPTestData\\CancelCellWithExistingCellReplacement.JSON"); var eventData = JsonConvert.DeserializeObject(cancelReplaceCellEventPayloadJson); + var permitKeys = new DecryptedPermit { ActiveKey = "firstkey", NextKey = "nextkey" }; XmlDocument soapXml = new(); soapXml.LoadXml(_sapXmlTemplate); A.CallTo(() => _fakeFileSystemHelper.IsFileExists(A.Ignored)).Returns(true); A.CallTo(() => _fakeXmlHelper.CreateXmlDocument(A.Ignored)).Returns(soapXml); + A.CallTo(() => _fakePermitDecryption.Decrypt(A.Ignored)).Returns(permitKeys); A.CallTo(() => _fakeWeekDetailsProvider.GetDateOfWeek(A.Ignored, A.Ignored, A.Ignored)).Returns("20240808"); var result = _fakeEncContentSapMessageBuilder.BuildSapMessageXml(eventData!); @@ -391,5 +393,46 @@ public void WhenGetXmlNodeValue(string fieldValue, string xmlNodeName, string ex result.Should().Be(expectedValue); } + + [Test] + [TestCase("ERPTestData\\NewCellWithNullYearInUkhoWeekNumberSection.JSON")] + [TestCase("ERPTestData\\NewCellWithoutYearInUkhoWeekNumberSection.JSON")] + [TestCase("ERPTestData\\NewCellWithNullcurrentWeekAlphaCorrectionInUkhoWeekNumberSection.JSON")] + public void WhenProcessingUkhoWeekNumberAttributes(string jsonPayloadFile) + { + var cancelCellWithNewCellReplacementPayloadJson = TestHelper.ReadFileData(jsonPayloadFile); + var eventData = JsonConvert.DeserializeObject(cancelCellWithNewCellReplacementPayloadJson); + var permitKeys = new DecryptedPermit { ActiveKey = "firstkey", NextKey = "nextkey" }; + + XmlDocument soapXml = new(); + soapXml.LoadXml(_sapXmlTemplate); + + A.CallTo(() => _fakeFileSystemHelper.IsFileExists(A.Ignored)).Returns(true); + A.CallTo(() => _fakeXmlHelper.CreateXmlDocument(A.Ignored)).Returns(soapXml); + A.CallTo(() => _fakePermitDecryption.Decrypt(A.Ignored)).Returns(permitKeys); + A.CallTo(() => _fakeWeekDetailsProvider.GetDateOfWeek(A.Ignored, A.Ignored, A.Ignored)).Throws(); + + Assert.Throws(() => _fakeEncContentSapMessageBuilder.BuildSapMessageXml(eventData!)) + .Message.Should().Be("Error while generating SAP action information. | Action : CREATE ENC CELL | XML Attribute : WEEKNO | ErrorMessage : Required details are missing in enccontentpublished event payload. | Property Name : "); + } + + [Test] + public void WhenBuildSapMessageXmlWithEmptyPermit_ThenThrowERPFacadeException() + { + var newCellEventPayloadJson = TestHelper.ReadFileData("ERPTestData\\NewCellWithEmptyPermit.JSON"); + var eventData = JsonConvert.DeserializeObject(newCellEventPayloadJson); + + XmlDocument soapXml = new(); + soapXml.LoadXml(_sapXmlTemplate); + + A.CallTo(() => _fakeFileSystemHelper.IsFileExists(A.Ignored)).Returns(true); + A.CallTo(() => _fakeXmlHelper.CreateXmlDocument(A.Ignored)).Returns(soapXml); + + A.CallTo(() => _fakeWeekDetailsProvider.GetDateOfWeek(A.Ignored, A.Ignored, A.Ignored)).Throws(); + A.CallTo(_fakePermitDecryption).Where(call => call.Method.Name == "Decrypt").MustNotHaveHappened(); + + Assert.Throws(() => _fakeEncContentSapMessageBuilder.BuildSapMessageXml(eventData!)) + .Message.Should().Be("Error while generating SAP action information. | Action : CREATE ENC CELL | XML Attribute : ACTIVEKEY | ErrorMessage : Required details are missing in enccontentpublished event payload. | Property Name : "); + } } } diff --git a/tests/UKHO.ERPFacade.API.UnitTests/Services/S57ServiceTests.cs b/tests/UKHO.ERPFacade.API.UnitTests/Services/S57ServiceTests.cs new file mode 100644 index 00000000..43656a5e --- /dev/null +++ b/tests/UKHO.ERPFacade.API.UnitTests/Services/S57ServiceTests.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Xml; +using FakeItEasy; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json.Linq; +using NUnit.Framework; +using UKHO.ERPFacade.API.Helpers; +using UKHO.ERPFacade.API.Services; +using UKHO.ERPFacade.API.UnitTests.Common; +using UKHO.ERPFacade.Common.Configuration; +using UKHO.ERPFacade.Common.Exceptions; +using UKHO.ERPFacade.Common.HttpClients; +using UKHO.ERPFacade.Common.IO.Azure; +using UKHO.ERPFacade.Common.Logging; +using UKHO.ERPFacade.Common.Models; +using UKHO.ERPFacade.Common.Models.TableEntities; + +namespace UKHO.ERPFacade.API.UnitTests.Services +{ + [TestFixture] + public class S57ServiceTests + { + private ILogger _fakeLogger; + private IAzureTableReaderWriter _fakeAzureTableReaderWriter; + private IAzureBlobEventWriter _fakeAzureBlobEventWriter; + private IAzureQueueHelper _fakeAzureQueueHelper; + private ISapClient _fakeSapClient; + private IEncContentSapMessageBuilder _fakeEncContentSapMessageBuilder; + private IOptions _fakeSapConfig; + private IOptions _fakeAioConfig; + private S57Service _fakeNewEncContentPublishedEventReceived; + + [SetUp] + public void Setup() + { + _fakeLogger = A.Fake>(); + _fakeAioConfig = A.Fake>(); + _fakeAzureTableReaderWriter = A.Fake(); + _fakeAzureBlobEventWriter = A.Fake(); + _fakeAzureQueueHelper = A.Fake(); + _fakeSapClient = A.Fake(); + _fakeEncContentSapMessageBuilder = A.Fake(); + _fakeSapConfig = Options.Create(new SapConfiguration() + { + SapServiceOperationForEncEvent = "Z_ADDS_MAT_INFO" + }); + + _fakeAioConfig.Value.AioCells = "GB800001,GB800002"; + + _fakeNewEncContentPublishedEventReceived = new S57Service(_fakeLogger, _fakeAzureTableReaderWriter, _fakeAzureBlobEventWriter, _fakeAzureQueueHelper, _fakeSapClient, _fakeEncContentSapMessageBuilder, _fakeSapConfig, _fakeAioConfig); + } + + [Test] + public void WhenSapDoesNotRespond200Ok_ThenReturn500InternalServerResponse() + { + XmlDocument xmlDocument = new(); + + var newCellEventPayloadJson = TestHelper.ReadFileData("ERPTestData\\NewCell.JSON"); + var fakeEncEventJson = JObject.Parse(newCellEventPayloadJson); + + A.CallTo(() => _fakeEncContentSapMessageBuilder.BuildSapMessageXml(A.Ignored)).Returns(xmlDocument); + A.CallTo(() => _fakeSapClient.PostEventData(A.Ignored, A.Ignored, A.Ignored, A.Ignored, A.Ignored)) + .Returns(new HttpResponseMessage() + { + StatusCode = HttpStatusCode.Unauthorized + }); + + Assert.ThrowsAsync(() => _fakeNewEncContentPublishedEventReceived.ProcessS57Event(fakeEncEventJson)) + .Message.Should().Be("An error occurred while sending a request to SAP. | Unauthorized"); + + A.CallTo(() => _fakeAzureTableReaderWriter.UpsertEntity(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.AddingEntryForEncContentPublishedEventInAzureTable.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Adding/Updating entry for enccontentpublished event in azure table.").MustHaveHappenedOnceExactly(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.UploadEncContentPublishedEventInAzureBlobStarted.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Uploading enccontentpublished event payload in blob storage.").MustHaveHappenedOnceExactly(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.UploadEncContentPublishedEventInAzureBlobCompleted.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "The enccontentpublished event payload is uploaded in blob storage successfully.").MustHaveHappenedOnceExactly(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.UploadSapXmlPayloadInAzureBlobStarted.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Uploading the SAP XML payload in blob storage.").MustHaveHappenedOnceExactly(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.UploadSapXmlPayloadInAzureBlobCompleted.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "SAP XML payload is uploaded in blob storage successfully.").MustHaveHappenedOnceExactly(); + } + + [Test] + public void WhenSapDoesResponds200Ok_ThenCheckAllRequiredMessagesLoggedAsExpected() + { + XmlDocument xmlDocument = new(); + + var newCellEventPayloadJson = TestHelper.ReadFileData("ERPTestData\\NewCell.JSON"); + var fakeEncEventJson = JObject.Parse(newCellEventPayloadJson); + + A.CallTo(() => _fakeEncContentSapMessageBuilder.BuildSapMessageXml(A.Ignored)).Returns(xmlDocument); + A.CallTo(() => _fakeSapClient.PostEventData(A.Ignored, A.Ignored, A.Ignored, A.Ignored, A.Ignored)) + .Returns(new HttpResponseMessage() + { + StatusCode = HttpStatusCode.OK + }); + + _ = _fakeNewEncContentPublishedEventReceived.ProcessS57Event(fakeEncEventJson); + + A.CallTo(() => _fakeAzureTableReaderWriter.UpdateEntity(A.Ignored, A.Ignored, A[]>.Ignored)).MustHaveHappened(); + A.CallTo(() => _fakeAzureBlobEventWriter.UploadEvent(A.Ignored, A.Ignored, A.Ignored)).MustHaveHappened(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.AddingEntryForEncContentPublishedEventInAzureTable.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Adding/Updating entry for enccontentpublished event in azure table.").MustHaveHappenedOnceExactly(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.UploadEncContentPublishedEventInAzureBlobStarted.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Uploading enccontentpublished event payload in blob storage.").MustHaveHappenedOnceExactly(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.UploadEncContentPublishedEventInAzureBlobCompleted.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "The enccontentpublished event payload is uploaded in blob storage successfully.").MustHaveHappenedOnceExactly(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.UploadSapXmlPayloadInAzureBlobStarted.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "Uploading the SAP XML payload in blob storage.").MustHaveHappenedOnceExactly(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.UploadSapXmlPayloadInAzureBlobCompleted.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "SAP XML payload is uploaded in blob storage successfully.").MustHaveHappenedOnceExactly(); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.EncUpdateSentToSap.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "ENC update has been sent to SAP successfully").MustHaveHappenedOnceExactly(); + } + + [Test] + public void WhenPayloadHasAioCells_ThenReturn200OkResponse() + { + var newCellEventPayloadJson = TestHelper.ReadFileData("ERPTestData\\NewAIOCell.JSON"); + var fakeEncEventJson = JObject.Parse(newCellEventPayloadJson); + + _ = _fakeNewEncContentPublishedEventReceived.ProcessS57Event(fakeEncEventJson); + + A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log" + && call.GetArgument(0) == LogLevel.Information + && call.GetArgument(1) == EventIds.NoProcessingOfNewEncContentPublishedEventForAioCells.ToEventId() + && call.GetArgument>>(2)!.ToDictionary(c => c.Key, c => c.Value)["{OriginalFormat}"].ToString() == "The enccontentpublished event will not be processed for Aio cells.").MustHaveHappenedOnceExactly(); + } + + [Test] + public void WhenBuildSapMessageXmlIsCalledWithoutAIOCellConfiguration_ThenThrowERPFacadeException() + { + _fakeAioConfig.Value.AioCells = string.Empty; + + Assert.Throws(() => new S57Service(_fakeLogger, _fakeAzureTableReaderWriter, _fakeAzureBlobEventWriter, _fakeAzureQueueHelper, _fakeSapClient, _fakeEncContentSapMessageBuilder, _fakeSapConfig, _fakeAioConfig)) + .Message.Should().Be("Aio cell configuration not found."); + } + } +} diff --git a/tests/UKHO.ERPFacade.API.UnitTests/UKHO.ERPFacade.API.UnitTests.csproj b/tests/UKHO.ERPFacade.API.UnitTests/UKHO.ERPFacade.API.UnitTests.csproj index 5dc94431..c980ddcf 100644 --- a/tests/UKHO.ERPFacade.API.UnitTests/UKHO.ERPFacade.API.UnitTests.csproj +++ b/tests/UKHO.ERPFacade.API.UnitTests/UKHO.ERPFacade.API.UnitTests.csproj @@ -39,6 +39,18 @@ Always + + Always + + + Always + + + Always + + + Always + Always