From 256e34329c750adf57df48d9ccaa0a54ec321ed3 Mon Sep 17 00:00:00 2001 From: Nikola Kukrika Date: Fri, 19 Jun 2026 11:51:58 +0200 Subject: [PATCH 1/5] [Shopify] Fix missing shop currency mapping on order transactions The amountSet.shopMoney.currencyCode was no longer mapped to the Currency field on order transactions after the code was moved from NAV to BCApps and presentment currency fields were added. This caused the Currency column on the Shopify Order Transactions page to be empty or retain stale values from the old REST API era. Fixes ICM 51000001074581 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al b/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al index ab6fa888f6..7b5d21159e 100644 --- a/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al +++ b/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al @@ -93,6 +93,7 @@ codeunit 30194 "Shpfy Transactions" JsonHelper.GetValueIntoField(JOrderTransaction, 'errorCode', RecordRef, OrderTransaction.FieldNo("Error Code")); JsonHelper.GetValueIntoField(JOrderTransaction, 'paymentId', RecordRef, OrderTransaction.FieldNo("Payment Id")); JsonHelper.GetValueIntoField(JOrderTransaction, 'amountSet.shopMoney.amount', RecordRef, OrderTransaction.FieldNo(Amount)); + JsonHelper.GetValueIntoField(JOrderTransaction, 'amountSet.shopMoney.currencyCode', RecordRef, OrderTransaction.FieldNo(Currency)); JsonHelper.GetValueIntoField(JOrderTransaction, 'amountSet.presentmentMoney.amount', RecordRef, OrderTransaction.FieldNo("Presentment Amount")); JsonHelper.GetValueIntoField(JOrderTransaction, 'amountSet.presentmentMoney.currencyCode', RecordRef, OrderTransaction.FieldNo("Presentment Currency")); JsonHelper.GetValueIntoField(JOrderTransaction, 'amountRoundingSet.shopMoney.amount', RecordRef, OrderTransaction.FieldNo("Rounding Amount")); From d25c0b23a739ce4fba7dbab0527de5ebb9f8d6ec Mon Sep 17 00:00:00 2001 From: Nikola Kukrika Date: Fri, 19 Jun 2026 14:02:36 +0200 Subject: [PATCH 2/5] Improve TranslateCurrencyCode: try Code match first, add telemetry - Early exit for empty input to avoid accidental ISO Code lookup - Try Currency.Get(code) first before falling back to ISO Code search - Add telemetry warning when multiple currencies share the same ISO Code Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Codeunits/ShpfyImportOrder.Codeunit.al | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/Apps/W1/Shopify/App/src/Order handling/Codeunits/ShpfyImportOrder.Codeunit.al b/src/Apps/W1/Shopify/App/src/Order handling/Codeunits/ShpfyImportOrder.Codeunit.al index 5d08f434e6..a6b6faa89b 100644 --- a/src/Apps/W1/Shopify/App/src/Order handling/Codeunits/ShpfyImportOrder.Codeunit.al +++ b/src/Apps/W1/Shopify/App/src/Order handling/Codeunits/ShpfyImportOrder.Codeunit.al @@ -77,6 +77,9 @@ codeunit 30161 "Shpfy Import Order" OrderEvents: Codeunit "Shpfy Order Events"; OrderFulfillments: Codeunit "Shpfy Order Fulfillments"; ProcessedConflictErr: Label 'The order has already been processed in Business Central, but an edition was received from Shopify. Changes were not propagated to the processed order in Business Central. Update the processed documents to match the received data from Shopify.'; + DuplicateISOCodeTelemetryLbl: Label 'Multiple currencies found with ISO Code %1. Count: %2.', Locked = true; + CurrencyNotFoundTelemetryLbl: Label 'No currency found with ISO Code %1.', Locked = true; + CategoryTok: Label 'Shopify Integration', Locked = true; local procedure ImportOrderAndCreateOrUpdate(ShopCode: Code[20]; OrderId: BigInteger) var @@ -651,15 +654,31 @@ codeunit 30161 "Shpfy Import Order" GeneralLedgerSetup: Record "General Ledger Setup"; CurrencyCode: Code[10]; begin + if ShopifyCurrencyCode = '' then + exit(''); + + GeneralLedgerSetup.Get(); + if CopyStr(ShopifyCurrencyCode, 1, MaxStrLen(GeneralLedgerSetup."LCY Code")) = GeneralLedgerSetup."LCY Code" then + exit(''); + Currency.SetLoadFields(Code); Currency.SetRange("ISO Code", CopyStr(ShopifyCurrencyCode, 1, 3)); - if Currency.FindFirst() then + if Currency.Count() = 1 then begin + Currency.FindFirst(); CurrencyCode := Currency.Code; - GeneralLedgerSetup.Get(); - if CurrencyCode = GeneralLedgerSetup."LCY Code" then - exit('') - else - exit(CurrencyCode); + end else begin + if Currency.Count() > 1 then begin + Session.LogMessage('0000S1A', StrSubstNo(DuplicateISOCodeTelemetryLbl, ShopifyCurrencyCode, Currency.Count()), Verbosity::Warning, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', CategoryTok); + Currency.FindFirst(); + CurrencyCode := Currency.Code; + end else + if Currency.Get(CopyStr(ShopifyCurrencyCode, 1, MaxStrLen(Currency.Code))) then + CurrencyCode := Currency.Code + else + Session.LogMessage('0000S1B', StrSubstNo(CurrencyNotFoundTelemetryLbl, ShopifyCurrencyCode), Verbosity::Warning, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', CategoryTok); + end; + + exit(CurrencyCode); end; local procedure ImportCustomAttributtes(ShopifyOrderId: BigInteger; JCustomAttributtes: JsonArray) From 52f3673b76ac04472266da9c89b41fd091de4985 Mon Sep 17 00:00:00 2001 From: Nikola Kukrika Date: Fri, 19 Jun 2026 15:07:15 +0200 Subject: [PATCH 3/5] Add transaction import tests for currency translation - Add ExtractShopifyOrderTransactionFromMock for testability - Create ShpfyTransactionsTest codeunit with scenario tests: - Import transaction sets Currency from shopMoney.currencyCode - Import transaction with LCY currency returns empty - Import transaction sets Presentment Currency correctly - Import transaction amounts match shopMoney/presentmentMoney - TranslateCurrencyCode unit tests for ISO match, empty input, Code fallback, and not-found scenarios Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Codeunits/ShpfyTransactions.Codeunit.al | 5 + .../ShpfyTransactionsTest.Codeunit.al | 333 ++++++++++++++++++ 2 files changed, 338 insertions(+) create mode 100644 src/Apps/W1/Shopify/Test/Transactions/ShpfyTransactionsTest.Codeunit.al diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al b/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al index 7b5d21159e..7fd383853b 100644 --- a/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al +++ b/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al @@ -42,6 +42,11 @@ codeunit 30194 "Shpfy Transactions" UpdateTransactionInfos(OrderHeader); end; + internal procedure ExtractShopifyOrderTransactionFromMock(JOrderTransaction: JsonToken; OrderHeader: Record "Shpfy Order Header") + begin + ExtractShopifyOrderTransaction(JOrderTransaction, OrderHeader); + end; + internal procedure UpdateTransactionInfos(OrderHeader: Record "Shpfy Order Header") var GraphQLType: Enum "Shpfy GraphQL Type"; diff --git a/src/Apps/W1/Shopify/Test/Transactions/ShpfyTransactionsTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Transactions/ShpfyTransactionsTest.Codeunit.al new file mode 100644 index 0000000000..aee5081a97 --- /dev/null +++ b/src/Apps/W1/Shopify/Test/Transactions/ShpfyTransactionsTest.Codeunit.al @@ -0,0 +1,333 @@ +// ------------------------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// ------------------------------------------------------------------------------------------------ + +namespace Microsoft.Integration.Shopify.Test; + +using Microsoft.Finance.Currency; +using Microsoft.Finance.GeneralLedger.Setup; +using Microsoft.Integration.Shopify; +using System.TestLibraries.Utilities; + +codeunit 139700 "Shpfy Transactions Test" +{ + Subtype = Test; + TestType = Uncategorized; + TestPermissions = Disabled; + + var + Shop: Record "Shpfy Shop"; + Any: Codeunit Any; + LibraryAssert: Codeunit "Library Assert"; + IsInitialized: Boolean; + + local procedure Initialize() + var + ShpfyInitializeTest: Codeunit "Shpfy Initialize Test"; + begin + if IsInitialized then + exit; + + Shop := ShpfyInitializeTest.CreateShop(); + IsInitialized := true; + end; + + [Test] + procedure ImportTransactionSetsShopCurrencyFromJson() + var + OrderHeader: Record "Shpfy Order Header"; + OrderTransaction: Record "Shpfy Order Transaction"; + Currency: Record Currency; + Transactions: Codeunit "Shpfy Transactions"; + LibraryERM: Codeunit "Library - ERM"; + JTransaction: JsonObject; + TransactionId: BigInteger; + CurrencyCode: Code[10]; + begin + // [SCENARIO] When importing a transaction, the Currency field is populated from shopMoney.currencyCode + Initialize(); + + // [GIVEN] A foreign currency with ISO Code + CurrencyCode := LibraryERM.CreateCurrencyWithRounding(); + Currency.Get(CurrencyCode); + Currency."ISO Code" := CopyStr(CurrencyCode, 1, MaxStrLen(Currency."ISO Code")); + Currency.Modify(); + + // [GIVEN] An order header + TransactionId := Any.IntegerInRange(100000, 999999); + OrderHeader.Init(); + OrderHeader."Shopify Order Id" := Any.IntegerInRange(100000, 999999); + OrderHeader."Shop Code" := Shop.Code; + if not OrderHeader.Insert() then + OrderHeader.Modify(); + + // [GIVEN] A transaction JSON with shopMoney.currencyCode set to the foreign currency + JTransaction := CreateTransactionJson(TransactionId, 100.00, CurrencyCode, 120.00, 'AUD'); + + // [WHEN] The transaction is extracted + Transactions.ExtractShopifyOrderTransactionFromMock(JTransaction.AsToken(), OrderHeader); + + // [THEN] OrderTransaction.Currency is set to the translated currency code + OrderTransaction.Get(TransactionId); + LibraryAssert.AreEqual(CurrencyCode, OrderTransaction.Currency, 'Currency should be set from shopMoney.currencyCode'); + end; + + [Test] + procedure ImportTransactionWithLCYCurrencyReturnsEmpty() + var + OrderHeader: Record "Shpfy Order Header"; + OrderTransaction: Record "Shpfy Order Transaction"; + GeneralLedgerSetup: Record "General Ledger Setup"; + Transactions: Codeunit "Shpfy Transactions"; + JTransaction: JsonObject; + TransactionId: BigInteger; + LCYCode: Code[10]; + begin + // [SCENARIO] When the shop currency matches LCY, the Currency field should be empty + Initialize(); + + // [GIVEN] The LCY code + GeneralLedgerSetup.Get(); + LCYCode := GeneralLedgerSetup."LCY Code"; + + // [GIVEN] An order header + TransactionId := Any.IntegerInRange(100000, 999999); + OrderHeader.Init(); + OrderHeader."Shopify Order Id" := Any.IntegerInRange(100000, 999999); + OrderHeader."Shop Code" := Shop.Code; + if not OrderHeader.Insert() then + OrderHeader.Modify(); + + // [GIVEN] A transaction JSON with shopMoney.currencyCode = LCY + JTransaction := CreateTransactionJson(TransactionId, 100.00, LCYCode, 100.00, LCYCode); + + // [WHEN] The transaction is extracted + Transactions.ExtractShopifyOrderTransactionFromMock(JTransaction.AsToken(), OrderHeader); + + // [THEN] OrderTransaction.Currency is empty (LCY is represented as blank in BC) + OrderTransaction.Get(TransactionId); + LibraryAssert.AreEqual('', OrderTransaction.Currency, 'Currency should be empty for LCY'); + end; + + [Test] + procedure ImportTransactionSetsPresentmentCurrencyFromJson() + var + OrderHeader: Record "Shpfy Order Header"; + OrderTransaction: Record "Shpfy Order Transaction"; + Currency: Record Currency; + GeneralLedgerSetup: Record "General Ledger Setup"; + Transactions: Codeunit "Shpfy Transactions"; + LibraryERM: Codeunit "Library - ERM"; + JTransaction: JsonObject; + TransactionId: BigInteger; + ShopCurrencyCode: Code[10]; + PresentmentCurrencyCode: Code[10]; + begin + // [SCENARIO] When importing a transaction, Presentment Currency is populated from presentmentMoney.currencyCode + Initialize(); + + // [GIVEN] A shop currency (LCY) + GeneralLedgerSetup.Get(); + ShopCurrencyCode := GeneralLedgerSetup."LCY Code"; + + // [GIVEN] A foreign presentment currency + PresentmentCurrencyCode := LibraryERM.CreateCurrencyWithRounding(); + Currency.Get(PresentmentCurrencyCode); + Currency."ISO Code" := CopyStr(PresentmentCurrencyCode, 1, MaxStrLen(Currency."ISO Code")); + Currency.Modify(); + + // [GIVEN] An order header + TransactionId := Any.IntegerInRange(100000, 999999); + OrderHeader.Init(); + OrderHeader."Shopify Order Id" := Any.IntegerInRange(100000, 999999); + OrderHeader."Shop Code" := Shop.Code; + if not OrderHeader.Insert() then + OrderHeader.Modify(); + + // [GIVEN] A transaction JSON with different shop and presentment currencies + JTransaction := CreateTransactionJson(TransactionId, 100.00, ShopCurrencyCode, 150.00, PresentmentCurrencyCode); + + // [WHEN] The transaction is extracted + Transactions.ExtractShopifyOrderTransactionFromMock(JTransaction.AsToken(), OrderHeader); + + // [THEN] Presentment Currency is set correctly + OrderTransaction.Get(TransactionId); + LibraryAssert.AreEqual('', OrderTransaction.Currency, 'Currency should be empty for LCY shop currency'); + LibraryAssert.AreEqual(PresentmentCurrencyCode, OrderTransaction."Presentment Currency", 'Presentment Currency should be set from presentmentMoney.currencyCode'); + end; + + [Test] + procedure ImportTransactionAmountMatchesShopMoney() + var + OrderHeader: Record "Shpfy Order Header"; + OrderTransaction: Record "Shpfy Order Transaction"; + GeneralLedgerSetup: Record "General Ledger Setup"; + Currency: Record Currency; + Transactions: Codeunit "Shpfy Transactions"; + LibraryERM: Codeunit "Library - ERM"; + JTransaction: JsonObject; + TransactionId: BigInteger; + ShopAmount: Decimal; + PresentmentAmount: Decimal; + PresentmentCurrencyCode: Code[10]; + begin + // [SCENARIO] Amount field contains shopMoney.amount and Presentment Amount contains presentmentMoney.amount + Initialize(); + + // [GIVEN] A foreign presentment currency + PresentmentCurrencyCode := LibraryERM.CreateCurrencyWithRounding(); + Currency.Get(PresentmentCurrencyCode); + Currency."ISO Code" := CopyStr(PresentmentCurrencyCode, 1, MaxStrLen(Currency."ISO Code")); + Currency.Modify(); + + // [GIVEN] An order header + GeneralLedgerSetup.Get(); + TransactionId := Any.IntegerInRange(100000, 999999); + ShopAmount := 85.50; + PresentmentAmount := 120.75; + OrderHeader.Init(); + OrderHeader."Shopify Order Id" := Any.IntegerInRange(100000, 999999); + OrderHeader."Shop Code" := Shop.Code; + if not OrderHeader.Insert() then + OrderHeader.Modify(); + + // [GIVEN] A transaction JSON with specific amounts + JTransaction := CreateTransactionJson(TransactionId, ShopAmount, GeneralLedgerSetup."LCY Code", PresentmentAmount, PresentmentCurrencyCode); + + // [WHEN] The transaction is extracted + Transactions.ExtractShopifyOrderTransactionFromMock(JTransaction.AsToken(), OrderHeader); + + // [THEN] Amounts are correctly mapped + OrderTransaction.Get(TransactionId); + LibraryAssert.AreEqual(ShopAmount, OrderTransaction.Amount, 'Amount should match shopMoney.amount'); + LibraryAssert.AreEqual(PresentmentAmount, OrderTransaction."Presentment Amount", 'Presentment Amount should match presentmentMoney.amount'); + end; + + [Test] + procedure TranslateCurrencyCodeWithISOCodeMatch() + var + Currency: Record Currency; + ImportOrder: Codeunit "Shpfy Import Order"; + LibraryERM: Codeunit "Library - ERM"; + CurrencyCode: Code[10]; + Result: Code[10]; + begin + // [SCENARIO] TranslateCurrencyCode finds currency by ISO Code when exactly one match exists + Initialize(); + + // [GIVEN] A currency with ISO Code set + CurrencyCode := LibraryERM.CreateCurrencyWithRounding(); + Currency.Get(CurrencyCode); + Currency."ISO Code" := 'ZZZ'; + Currency.Modify(); + + // [WHEN] TranslateCurrencyCode is called with the ISO Code + ImportOrder.SetShop(Shop.Code); + Result := ImportOrder.TranslateCurrencyCode('ZZZ'); + + // [THEN] The currency code is returned + LibraryAssert.AreEqual(CurrencyCode, Result, 'Should return currency code matching ISO Code'); + end; + + [Test] + procedure TranslateCurrencyCodeWithEmptyInput() + var + ImportOrder: Codeunit "Shpfy Import Order"; + Result: Code[10]; + begin + // [SCENARIO] TranslateCurrencyCode returns empty for empty input + Initialize(); + + // [WHEN] TranslateCurrencyCode is called with empty string + ImportOrder.SetShop(Shop.Code); + Result := ImportOrder.TranslateCurrencyCode(''); + + // [THEN] Returns empty + LibraryAssert.AreEqual('', Result, 'Should return empty for empty input'); + end; + + [Test] + procedure TranslateCurrencyCodeFallsBackToCodeMatch() + var + Currency: Record Currency; + ImportOrder: Codeunit "Shpfy Import Order"; + LibraryERM: Codeunit "Library - ERM"; + CurrencyCode: Code[10]; + Result: Code[10]; + begin + // [SCENARIO] When no currency matches by ISO Code, TranslateCurrencyCode falls back to Currency.Get(code) + Initialize(); + + // [GIVEN] A currency whose Code matches the input but ISO Code does not + CurrencyCode := LibraryERM.CreateCurrencyWithRounding(); + Currency.Get(CurrencyCode); + Currency."ISO Code" := 'XXX'; + Currency.Modify(); + + // [WHEN] TranslateCurrencyCode is called with the currency code (not matching any ISO Code) + ImportOrder.SetShop(Shop.Code); + Result := ImportOrder.TranslateCurrencyCode(CurrencyCode); + + // [THEN] The currency code is returned via Get fallback + LibraryAssert.AreEqual(CurrencyCode, Result, 'Should find currency by Code when ISO Code does not match'); + end; + + [Test] + procedure TranslateCurrencyCodeReturnsEmptyWhenNotFound() + var + ImportOrder: Codeunit "Shpfy Import Order"; + Result: Code[10]; + begin + // [SCENARIO] TranslateCurrencyCode returns empty when currency is not found by ISO Code or Code + Initialize(); + + // [WHEN] TranslateCurrencyCode is called with a non-existent currency code + ImportOrder.SetShop(Shop.Code); + Result := ImportOrder.TranslateCurrencyCode('QQQ'); + + // [THEN] Returns empty + LibraryAssert.AreEqual('', Result, 'Should return empty when currency not found'); + end; + + local procedure CreateTransactionJson(TransactionId: BigInteger; ShopAmount: Decimal; ShopCurrencyCode: Code[10]; PresentmentAmount: Decimal; PresentmentCurrencyCode: Code[10]) JTransaction: JsonObject + var + JAmountSet: JsonObject; + JShopMoney: JsonObject; + JPresentmentMoney: JsonObject; + JAmountRoundingSet: JsonObject; + JRoundingShopMoney: JsonObject; + JRoundingPresentmentMoney: JsonObject; + TransactionGidLbl: Label 'gid://shopify/OrderTransaction/%1', Comment = '%1 = id', Locked = true; + begin + JTransaction.Add('id', StrSubstNo(TransactionGidLbl, TransactionId)); + JTransaction.Add('gateway', 'shopify_payments'); + JTransaction.Add('formattedGateway', 'Shopify Payments'); + JTransaction.Add('manualPaymentGateway', ''); + JTransaction.Add('createdAt', Format(CurrentDateTime(), 0, 9)); + JTransaction.Add('test', false); + JTransaction.Add('authorizationCode', ''); + JTransaction.Add('errorCode', ''); + JTransaction.Add('paymentId', StrSubstNo(TransactionGidLbl, Any.IntegerInRange(100000, 999999))); + JTransaction.Add('status', 'SUCCESS'); + JTransaction.Add('kind', 'SALE'); + + JShopMoney.Add('amount', ShopAmount); + JShopMoney.Add('currencyCode', ShopCurrencyCode); + JPresentmentMoney.Add('amount', PresentmentAmount); + JPresentmentMoney.Add('currencyCode', PresentmentCurrencyCode); + JAmountSet.Add('shopMoney', JShopMoney); + JAmountSet.Add('presentmentMoney', JPresentmentMoney); + JTransaction.Add('amountSet', JAmountSet); + + JRoundingShopMoney.Add('amount', 0); + JRoundingShopMoney.Add('currencyCode', ShopCurrencyCode); + JRoundingPresentmentMoney.Add('amount', 0); + JRoundingPresentmentMoney.Add('currencyCode', PresentmentCurrencyCode); + JAmountRoundingSet.Add('shopMoney', JRoundingShopMoney); + JAmountRoundingSet.Add('presentmentMoney', JRoundingPresentmentMoney); + JTransaction.Add('amountRoundingSet', JAmountRoundingSet); + + JTransaction.Add('receiptJson', '{}'); + end; +} From aab69156c6c264f71055e177869d86ceadca206e Mon Sep 17 00:00:00 2001 From: Nikola Kukrika Date: Fri, 19 Jun 2026 16:39:29 +0200 Subject: [PATCH 4/5] Rewrite transaction tests to use HTTP handler pattern Remove mock entry point from ShpfyTransactions.Codeunit.al and rewrite tests to use [HttpClientHandler] pattern with Library - Variable Storage for dynamic JSON responses. Tests now exercise the full transaction import flow through the real HTTP pipeline. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Codeunits/ShpfyTransactions.Codeunit.al | 5 - .../ShpfyTransactionsTest.Codeunit.al | 250 ++++++++++-------- 2 files changed, 139 insertions(+), 116 deletions(-) diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al b/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al index 7fd383853b..7b5d21159e 100644 --- a/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al +++ b/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyTransactions.Codeunit.al @@ -42,11 +42,6 @@ codeunit 30194 "Shpfy Transactions" UpdateTransactionInfos(OrderHeader); end; - internal procedure ExtractShopifyOrderTransactionFromMock(JOrderTransaction: JsonToken; OrderHeader: Record "Shpfy Order Header") - begin - ExtractShopifyOrderTransaction(JOrderTransaction, OrderHeader); - end; - internal procedure UpdateTransactionInfos(OrderHeader: Record "Shpfy Order Header") var GraphQLType: Enum "Shpfy GraphQL Type"; diff --git a/src/Apps/W1/Shopify/Test/Transactions/ShpfyTransactionsTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Transactions/ShpfyTransactionsTest.Codeunit.al index aee5081a97..308eaa22d4 100644 --- a/src/Apps/W1/Shopify/Test/Transactions/ShpfyTransactionsTest.Codeunit.al +++ b/src/Apps/W1/Shopify/Test/Transactions/ShpfyTransactionsTest.Codeunit.al @@ -15,34 +15,48 @@ codeunit 139700 "Shpfy Transactions Test" Subtype = Test; TestType = Uncategorized; TestPermissions = Disabled; + TestHttpRequestPolicy = BlockOutboundRequests; var Shop: Record "Shpfy Shop"; Any: Codeunit Any; LibraryAssert: Codeunit "Library Assert"; + LibraryRandom: Codeunit "Library - Random"; + CommunicationMgt: Codeunit "Shpfy Communication Mgt."; + InitializeTest: Codeunit "Shpfy Initialize Test"; + TransactionData: Codeunit "Library - Variable Storage"; IsInitialized: Boolean; local procedure Initialize() var - ShpfyInitializeTest: Codeunit "Shpfy Initialize Test"; + AccessToken: SecretText; begin if IsInitialized then exit; - Shop := ShpfyInitializeTest.CreateShop(); + Codeunit.Run(Codeunit::"Shpfy Initialize Test"); + Shop := CommunicationMgt.GetShopRecord(); + + AccessToken := LibraryRandom.RandText(20); + InitializeTest.RegisterAccessTokenForShop(Shop.GetStoreName(), AccessToken); + + Commit(); IsInitialized := true; end; [Test] + [HandlerFunctions('TransactionHttpHandler')] procedure ImportTransactionSetsShopCurrencyFromJson() var OrderHeader: Record "Shpfy Order Header"; OrderTransaction: Record "Shpfy Order Transaction"; Currency: Record Currency; - Transactions: Codeunit "Shpfy Transactions"; + ImportOrder: Codeunit "Shpfy Import Order"; + OrderHandlingHelper: Codeunit "Shpfy Order Handling Helper"; LibraryERM: Codeunit "Library - ERM"; - JTransaction: JsonObject; - TransactionId: BigInteger; + OrdersToImport: Record "Shpfy Orders to Import"; + JShopifyOrder: JsonObject; + JShopifyLineItems: JsonArray; CurrencyCode: Code[10]; begin // [SCENARIO] When importing a transaction, the Currency field is populated from shopMoney.currencyCode @@ -54,34 +68,40 @@ codeunit 139700 "Shpfy Transactions Test" Currency."ISO Code" := CopyStr(CurrencyCode, 1, MaxStrLen(Currency."ISO Code")); Currency.Modify(); - // [GIVEN] An order header - TransactionId := Any.IntegerInRange(100000, 999999); - OrderHeader.Init(); - OrderHeader."Shopify Order Id" := Any.IntegerInRange(100000, 999999); - OrderHeader."Shop Code" := Shop.Code; - if not OrderHeader.Insert() then - OrderHeader.Modify(); + // [GIVEN] Set up mock transaction response with foreign shop currency + TransactionData.Clear(); + TransactionData.Enqueue(CurrencyCode); // shopMoney.currencyCode + TransactionData.Enqueue(100.00); // shopMoney.amount + TransactionData.Enqueue('AUD'); // presentmentMoney.currencyCode + TransactionData.Enqueue(120.00); // presentmentMoney.amount - // [GIVEN] A transaction JSON with shopMoney.currencyCode set to the foreign currency - JTransaction := CreateTransactionJson(TransactionId, 100.00, CurrencyCode, 120.00, 'AUD'); - - // [WHEN] The transaction is extracted - Transactions.ExtractShopifyOrderTransactionFromMock(JTransaction.AsToken(), OrderHeader); + // [GIVEN] A Shopify order is imported + ImportOrder.SetShop(Shop.Code); + JShopifyOrder := OrderHandlingHelper.CreateShopifyOrderAsJson(Shop, OrdersToImport, JShopifyLineItems, false); + ImportOrder.ImportCreateAndUpdateOrderHeaderFromMock(Shop.Code, OrdersToImport.Id, JShopifyOrder); + ImportOrder.ImportCreateAndUpdateOrderLinesFromMock(OrdersToImport.Id, JShopifyLineItems); + Commit(); + OrderHeader.Get(OrdersToImport.Id); // [THEN] OrderTransaction.Currency is set to the translated currency code - OrderTransaction.Get(TransactionId); + OrderTransaction.SetRange("Shopify Order Id", OrderHeader."Shopify Order Id"); + OrderTransaction.SetRange(Status, "Shpfy Transaction Status"::Success); + LibraryAssert.IsTrue(OrderTransaction.FindFirst(), 'Transaction should be created'); LibraryAssert.AreEqual(CurrencyCode, OrderTransaction.Currency, 'Currency should be set from shopMoney.currencyCode'); end; [Test] + [HandlerFunctions('TransactionHttpHandler')] procedure ImportTransactionWithLCYCurrencyReturnsEmpty() var OrderHeader: Record "Shpfy Order Header"; OrderTransaction: Record "Shpfy Order Transaction"; GeneralLedgerSetup: Record "General Ledger Setup"; - Transactions: Codeunit "Shpfy Transactions"; - JTransaction: JsonObject; - TransactionId: BigInteger; + ImportOrder: Codeunit "Shpfy Import Order"; + OrderHandlingHelper: Codeunit "Shpfy Order Handling Helper"; + OrdersToImport: Record "Shpfy Orders to Import"; + JShopifyOrder: JsonObject; + JShopifyLineItems: JsonArray; LCYCode: Code[10]; begin // [SCENARIO] When the shop currency matches LCY, the Currency field should be empty @@ -91,115 +111,128 @@ codeunit 139700 "Shpfy Transactions Test" GeneralLedgerSetup.Get(); LCYCode := GeneralLedgerSetup."LCY Code"; - // [GIVEN] An order header - TransactionId := Any.IntegerInRange(100000, 999999); - OrderHeader.Init(); - OrderHeader."Shopify Order Id" := Any.IntegerInRange(100000, 999999); - OrderHeader."Shop Code" := Shop.Code; - if not OrderHeader.Insert() then - OrderHeader.Modify(); + // [GIVEN] Set up mock transaction response with LCY as shop currency + TransactionData.Clear(); + TransactionData.Enqueue(LCYCode); + TransactionData.Enqueue(100.00); + TransactionData.Enqueue(LCYCode); + TransactionData.Enqueue(100.00); - // [GIVEN] A transaction JSON with shopMoney.currencyCode = LCY - JTransaction := CreateTransactionJson(TransactionId, 100.00, LCYCode, 100.00, LCYCode); - - // [WHEN] The transaction is extracted - Transactions.ExtractShopifyOrderTransactionFromMock(JTransaction.AsToken(), OrderHeader); + // [GIVEN] A Shopify order is imported + ImportOrder.SetShop(Shop.Code); + JShopifyOrder := OrderHandlingHelper.CreateShopifyOrderAsJson(Shop, OrdersToImport, JShopifyLineItems, false); + ImportOrder.ImportCreateAndUpdateOrderHeaderFromMock(Shop.Code, OrdersToImport.Id, JShopifyOrder); + ImportOrder.ImportCreateAndUpdateOrderLinesFromMock(OrdersToImport.Id, JShopifyLineItems); + Commit(); + OrderHeader.Get(OrdersToImport.Id); // [THEN] OrderTransaction.Currency is empty (LCY is represented as blank in BC) - OrderTransaction.Get(TransactionId); + OrderTransaction.SetRange("Shopify Order Id", OrderHeader."Shopify Order Id"); + OrderTransaction.SetRange(Status, "Shpfy Transaction Status"::Success); + LibraryAssert.IsTrue(OrderTransaction.FindFirst(), 'Transaction should be created'); LibraryAssert.AreEqual('', OrderTransaction.Currency, 'Currency should be empty for LCY'); end; [Test] + [HandlerFunctions('TransactionHttpHandler')] procedure ImportTransactionSetsPresentmentCurrencyFromJson() var OrderHeader: Record "Shpfy Order Header"; OrderTransaction: Record "Shpfy Order Transaction"; Currency: Record Currency; GeneralLedgerSetup: Record "General Ledger Setup"; - Transactions: Codeunit "Shpfy Transactions"; + ImportOrder: Codeunit "Shpfy Import Order"; + OrderHandlingHelper: Codeunit "Shpfy Order Handling Helper"; LibraryERM: Codeunit "Library - ERM"; - JTransaction: JsonObject; - TransactionId: BigInteger; - ShopCurrencyCode: Code[10]; + OrdersToImport: Record "Shpfy Orders to Import"; + JShopifyOrder: JsonObject; + JShopifyLineItems: JsonArray; PresentmentCurrencyCode: Code[10]; + LCYCode: Code[10]; begin // [SCENARIO] When importing a transaction, Presentment Currency is populated from presentmentMoney.currencyCode Initialize(); - // [GIVEN] A shop currency (LCY) + // [GIVEN] LCY code and a foreign presentment currency GeneralLedgerSetup.Get(); - ShopCurrencyCode := GeneralLedgerSetup."LCY Code"; - - // [GIVEN] A foreign presentment currency + LCYCode := GeneralLedgerSetup."LCY Code"; PresentmentCurrencyCode := LibraryERM.CreateCurrencyWithRounding(); Currency.Get(PresentmentCurrencyCode); Currency."ISO Code" := CopyStr(PresentmentCurrencyCode, 1, MaxStrLen(Currency."ISO Code")); Currency.Modify(); - // [GIVEN] An order header - TransactionId := Any.IntegerInRange(100000, 999999); - OrderHeader.Init(); - OrderHeader."Shopify Order Id" := Any.IntegerInRange(100000, 999999); - OrderHeader."Shop Code" := Shop.Code; - if not OrderHeader.Insert() then - OrderHeader.Modify(); + // [GIVEN] Set up mock transaction response with LCY shop currency and foreign presentment + TransactionData.Clear(); + TransactionData.Enqueue(LCYCode); + TransactionData.Enqueue(100.00); + TransactionData.Enqueue(PresentmentCurrencyCode); + TransactionData.Enqueue(150.00); - // [GIVEN] A transaction JSON with different shop and presentment currencies - JTransaction := CreateTransactionJson(TransactionId, 100.00, ShopCurrencyCode, 150.00, PresentmentCurrencyCode); - - // [WHEN] The transaction is extracted - Transactions.ExtractShopifyOrderTransactionFromMock(JTransaction.AsToken(), OrderHeader); + // [GIVEN] A Shopify order is imported + ImportOrder.SetShop(Shop.Code); + JShopifyOrder := OrderHandlingHelper.CreateShopifyOrderAsJson(Shop, OrdersToImport, JShopifyLineItems, false); + ImportOrder.ImportCreateAndUpdateOrderHeaderFromMock(Shop.Code, OrdersToImport.Id, JShopifyOrder); + ImportOrder.ImportCreateAndUpdateOrderLinesFromMock(OrdersToImport.Id, JShopifyLineItems); + Commit(); + OrderHeader.Get(OrdersToImport.Id); // [THEN] Presentment Currency is set correctly - OrderTransaction.Get(TransactionId); + OrderTransaction.SetRange("Shopify Order Id", OrderHeader."Shopify Order Id"); + OrderTransaction.SetRange(Status, "Shpfy Transaction Status"::Success); + LibraryAssert.IsTrue(OrderTransaction.FindFirst(), 'Transaction should be created'); LibraryAssert.AreEqual('', OrderTransaction.Currency, 'Currency should be empty for LCY shop currency'); LibraryAssert.AreEqual(PresentmentCurrencyCode, OrderTransaction."Presentment Currency", 'Presentment Currency should be set from presentmentMoney.currencyCode'); end; [Test] + [HandlerFunctions('TransactionHttpHandler')] procedure ImportTransactionAmountMatchesShopMoney() var OrderHeader: Record "Shpfy Order Header"; OrderTransaction: Record "Shpfy Order Transaction"; - GeneralLedgerSetup: Record "General Ledger Setup"; Currency: Record Currency; - Transactions: Codeunit "Shpfy Transactions"; + GeneralLedgerSetup: Record "General Ledger Setup"; + ImportOrder: Codeunit "Shpfy Import Order"; + OrderHandlingHelper: Codeunit "Shpfy Order Handling Helper"; LibraryERM: Codeunit "Library - ERM"; - JTransaction: JsonObject; - TransactionId: BigInteger; + OrdersToImport: Record "Shpfy Orders to Import"; + JShopifyOrder: JsonObject; + JShopifyLineItems: JsonArray; + PresentmentCurrencyCode: Code[10]; ShopAmount: Decimal; PresentmentAmount: Decimal; - PresentmentCurrencyCode: Code[10]; begin // [SCENARIO] Amount field contains shopMoney.amount and Presentment Amount contains presentmentMoney.amount Initialize(); // [GIVEN] A foreign presentment currency + GeneralLedgerSetup.Get(); PresentmentCurrencyCode := LibraryERM.CreateCurrencyWithRounding(); Currency.Get(PresentmentCurrencyCode); Currency."ISO Code" := CopyStr(PresentmentCurrencyCode, 1, MaxStrLen(Currency."ISO Code")); Currency.Modify(); - // [GIVEN] An order header - GeneralLedgerSetup.Get(); - TransactionId := Any.IntegerInRange(100000, 999999); + // [GIVEN] Set up mock transaction response with specific amounts ShopAmount := 85.50; PresentmentAmount := 120.75; - OrderHeader.Init(); - OrderHeader."Shopify Order Id" := Any.IntegerInRange(100000, 999999); - OrderHeader."Shop Code" := Shop.Code; - if not OrderHeader.Insert() then - OrderHeader.Modify(); + TransactionData.Clear(); + TransactionData.Enqueue(GeneralLedgerSetup."LCY Code"); + TransactionData.Enqueue(ShopAmount); + TransactionData.Enqueue(PresentmentCurrencyCode); + TransactionData.Enqueue(PresentmentAmount); - // [GIVEN] A transaction JSON with specific amounts - JTransaction := CreateTransactionJson(TransactionId, ShopAmount, GeneralLedgerSetup."LCY Code", PresentmentAmount, PresentmentCurrencyCode); - - // [WHEN] The transaction is extracted - Transactions.ExtractShopifyOrderTransactionFromMock(JTransaction.AsToken(), OrderHeader); + // [GIVEN] A Shopify order is imported + ImportOrder.SetShop(Shop.Code); + JShopifyOrder := OrderHandlingHelper.CreateShopifyOrderAsJson(Shop, OrdersToImport, JShopifyLineItems, false); + ImportOrder.ImportCreateAndUpdateOrderHeaderFromMock(Shop.Code, OrdersToImport.Id, JShopifyOrder); + ImportOrder.ImportCreateAndUpdateOrderLinesFromMock(OrdersToImport.Id, JShopifyLineItems); + Commit(); + OrderHeader.Get(OrdersToImport.Id); // [THEN] Amounts are correctly mapped - OrderTransaction.Get(TransactionId); + OrderTransaction.SetRange("Shopify Order Id", OrderHeader."Shopify Order Id"); + OrderTransaction.SetRange(Status, "Shpfy Transaction Status"::Success); + LibraryAssert.IsTrue(OrderTransaction.FindFirst(), 'Transaction should be created'); LibraryAssert.AreEqual(ShopAmount, OrderTransaction.Amount, 'Amount should match shopMoney.amount'); LibraryAssert.AreEqual(PresentmentAmount, OrderTransaction."Presentment Amount", 'Presentment Amount should match presentmentMoney.amount'); end; @@ -290,44 +323,39 @@ codeunit 139700 "Shpfy Transactions Test" LibraryAssert.AreEqual('', Result, 'Should return empty when currency not found'); end; - local procedure CreateTransactionJson(TransactionId: BigInteger; ShopAmount: Decimal; ShopCurrencyCode: Code[10]; PresentmentAmount: Decimal; PresentmentCurrencyCode: Code[10]) JTransaction: JsonObject + [HttpClientHandler] + internal procedure TransactionHttpHandler(Request: TestHttpRequestMessage; var Response: TestHttpResponseMessage): Boolean var - JAmountSet: JsonObject; - JShopMoney: JsonObject; - JPresentmentMoney: JsonObject; - JAmountRoundingSet: JsonObject; - JRoundingShopMoney: JsonObject; - JRoundingPresentmentMoney: JsonObject; - TransactionGidLbl: Label 'gid://shopify/OrderTransaction/%1', Comment = '%1 = id', Locked = true; + ShopCurrencyCode: Text; + ShopAmount: Decimal; + PresentmentCurrencyCode: Text; + PresentmentAmount: Decimal; + TransactionId: BigInteger; + Body: Text; + TransactionResponseLbl: Label '{"data":{"order":{"transactions":[{"authorizationCode":"","createdAt":"%1","errorCode":null,"formattedGateway":"Shopify Payments","gateway":"shopify_payments","id":"gid://shopify/OrderTransaction/%2","kind":"SALE","paymentId":"gid://shopify/Payment/%3","receiptJson":"{}","status":"SUCCESS","test":true,"amountSet":{"shopMoney":{"amount":"%4","currencyCode":"%5"},"presentmentMoney":{"amount":"%6","currencyCode":"%7"}},"amountRoundingSet":{"shopMoney":{"amount":"0","currencyCode":"%5"},"presentmentMoney":{"amount":"0","currencyCode":"%7"}},"paymentDetails":null}]}},"extensions":{"cost":{"requestedQueryCost":3,"actualQueryCost":3,"throttleStatus":{"maximumAvailable":2000.0,"currentlyAvailable":1997,"restoreRate":100.0}}}}', Locked = true; begin - JTransaction.Add('id', StrSubstNo(TransactionGidLbl, TransactionId)); - JTransaction.Add('gateway', 'shopify_payments'); - JTransaction.Add('formattedGateway', 'Shopify Payments'); - JTransaction.Add('manualPaymentGateway', ''); - JTransaction.Add('createdAt', Format(CurrentDateTime(), 0, 9)); - JTransaction.Add('test', false); - JTransaction.Add('authorizationCode', ''); - JTransaction.Add('errorCode', ''); - JTransaction.Add('paymentId', StrSubstNo(TransactionGidLbl, Any.IntegerInRange(100000, 999999))); - JTransaction.Add('status', 'SUCCESS'); - JTransaction.Add('kind', 'SALE'); - - JShopMoney.Add('amount', ShopAmount); - JShopMoney.Add('currencyCode', ShopCurrencyCode); - JPresentmentMoney.Add('amount', PresentmentAmount); - JPresentmentMoney.Add('currencyCode', PresentmentCurrencyCode); - JAmountSet.Add('shopMoney', JShopMoney); - JAmountSet.Add('presentmentMoney', JPresentmentMoney); - JTransaction.Add('amountSet', JAmountSet); - - JRoundingShopMoney.Add('amount', 0); - JRoundingShopMoney.Add('currencyCode', ShopCurrencyCode); - JRoundingPresentmentMoney.Add('amount', 0); - JRoundingPresentmentMoney.Add('currencyCode', PresentmentCurrencyCode); - JAmountRoundingSet.Add('shopMoney', JRoundingShopMoney); - JAmountRoundingSet.Add('presentmentMoney', JRoundingPresentmentMoney); - JTransaction.Add('amountRoundingSet', JAmountRoundingSet); - - JTransaction.Add('receiptJson', '{}'); + if not InitializeTest.VerifyRequestUrl(Request.Path, Shop."Shopify URL") then + exit(true); + + if TransactionData.Length() > 0 then begin + ShopCurrencyCode := TransactionData.DequeueText(); + ShopAmount := TransactionData.DequeueDecimal(); + PresentmentCurrencyCode := TransactionData.DequeueText(); + PresentmentAmount := TransactionData.DequeueDecimal(); + TransactionId := Any.IntegerInRange(100000, 999999); + Body := StrSubstNo( + TransactionResponseLbl, + Format(CurrentDateTime(), 0, 9), + TransactionId, + Any.IntegerInRange(100000, 999999), + Format(ShopAmount, 0, 9), + ShopCurrencyCode, + Format(PresentmentAmount, 0, 9), + PresentmentCurrencyCode + ); + Response.Content.WriteFrom(Body); + end else + Response.Content.WriteFrom('{"data":{"order":{"transactions":[]}}}'); + exit(false); end; } From d5752fc18b6c959d56a2aa0ae1b85fa37d8d7ab2 Mon Sep 17 00:00:00 2001 From: Nikola Kukrika Date: Fri, 19 Jun 2026 17:02:47 +0200 Subject: [PATCH 5/5] Update ShpfyShippingChargesTest to validate transaction currency Add DKK currency setup in Initialize to support the existing resource file (OrderTransactionResult.txt uses DKK). Add new test that validates transaction Currency and Presentment Currency are correctly populated from shopMoney/presentmentMoney in the JSON response during order import. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../ShpfyShippingChargesTest.Codeunit.al | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingChargesTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingChargesTest.Codeunit.al index f32abf44c8..477b0e4a07 100644 --- a/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingChargesTest.Codeunit.al +++ b/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingChargesTest.Codeunit.al @@ -5,7 +5,9 @@ namespace Microsoft.Integration.Shopify.Test; +using Microsoft.Finance.Currency; using Microsoft.Finance.GeneralLedger.Account; +using Microsoft.Finance.GeneralLedger.Setup; using Microsoft.Finance.VAT.Setup; using Microsoft.Foundation.Enums; using Microsoft.Foundation.Shipping; @@ -353,6 +355,47 @@ codeunit 139546 "Shpfy Shipping Charges Test" ShpfyShipmentMethodMapping."Shipping Charges No." ); end; + + [Test] + [HandlerFunctions('ShippingChargesHttpHandler')] + procedure UnitTestTransactionCurrencyIsSetFromOrderImport() + var + OrderHeader: Record "Shpfy Order Header"; + OrderTransaction: Record "Shpfy Order Transaction"; + GeneralLedgerSetup: Record "General Ledger Setup"; + ImportOrder: Codeunit "Shpfy Import Order"; + begin + // [SCENARIO] When importing a Shopify order, the transaction currency is correctly populated from the JSON response. + Initialize(); + + // [GIVEN] Shopify Shop + Shop := CommunicationMgt.GetShopRecord(); + + // [GIVEN] Register Expected Outbound API Requests. + OutboundHttpRequests.Clear(); + OutboundHttpRequests.Enqueue('Transactions'); + + // [GIVEN] Shopify order is imported + ImportOrder.SetShop(Shop.Code); + ImportShopifyOrder(Shop, OrderHeader, ImportOrder, false); + + // [THEN] Transaction is created with the correct currency from shopMoney.currencyCode (DKK from resource file) + OrderTransaction.SetRange("Shopify Order Id", OrderHeader."Shopify Order Id"); + OrderTransaction.SetRange(Status, "Shpfy Transaction Status"::Success); + LibraryAssert.IsTrue(OrderTransaction.FindFirst(), 'Transaction should be created'); + + GeneralLedgerSetup.Get(); + if 'DKK' = GeneralLedgerSetup."LCY Code" then + LibraryAssert.AreEqual('', OrderTransaction.Currency, 'Currency should be empty when DKK is LCY') + else + LibraryAssert.AreEqual('DKK', OrderTransaction.Currency, 'Currency should be DKK from shopMoney.currencyCode'); + + // [THEN] Presentment currency is also set correctly + if 'DKK' = GeneralLedgerSetup."LCY Code" then + LibraryAssert.AreEqual('', OrderTransaction."Presentment Currency", 'Presentment Currency should be empty when DKK is LCY') + else + LibraryAssert.AreEqual('DKK', OrderTransaction."Presentment Currency", 'Presentment Currency should be DKK from presentmentMoney.currencyCode'); + end; #endregion [HttpClientHandler] @@ -386,6 +429,7 @@ codeunit 139546 "Shpfy Shipping Charges Test" #region Local Procedures local procedure Initialize() var + Currency: Record Currency; ShippingTime: DateFormula; AccessToken: SecretText; begin @@ -403,6 +447,17 @@ codeunit 139546 "Shpfy Shipping Charges Test" LibraryInventory.CreateShippingAgent(ShippingAgent); LibraryInventory.CreateShippingAgentService(ShippingAgentServices, ShippingAgent.Code, ShippingTime); + if not Currency.Get('DKK') then begin + Currency.Init(); + Currency.Code := 'DKK'; + Currency."ISO Code" := 'DKK'; + Currency.Insert(true); + end else + if Currency."ISO Code" <> 'DKK' then begin + Currency."ISO Code" := 'DKK'; + Currency.Modify(); + end; + Commit(); IsInitialized := true;