From 348a06b2c49471ad0c2b2f476f1bd8a89d7c8d97 Mon Sep 17 00:00:00 2001 From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com> Date: Tue, 19 May 2026 20:49:13 +0200 Subject: [PATCH 1/3] [Shopify] Auto Create Catalog: always visible, validate plan on enable PR #7605 made B2B unconditional but the "Auto Create Catalog" toggle on Shop Card stayed hidden for non-Advanced shops because its `Visible = Rec."Advanced Shopify Plan"` binding is not re-evaluated after GetShopSettings() runs. Drop the dynamic visibility and gate the field at the table layer instead: an OnValidate trigger raises a field error if the user tries to enable Auto Create Catalog on a shop whose plan does not support B2B catalogs. Adds a test in ShpfyStaffTest (already the home for plan-gated tests) covering both the rejection path and the success path after the plan flag is set. Fixes AB#630316 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../App/src/Base/Pages/ShpfyShopCard.Page.al | 1 - .../App/src/Base/Tables/ShpfyShop.Table.al | 14 ++++++++++ .../Test/Staff/ShpfyStaffTest.Codeunit.al | 27 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al b/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al index 5cb2a5d3c1..9d574d9cdd 100644 --- a/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al +++ b/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al @@ -395,7 +395,6 @@ page 30101 "Shpfy Shop Card" field("Auto Create Catalog"; Rec."Auto Create Catalog") { ApplicationArea = All; - Visible = Rec."Advanced Shopify Plan"; } field("Company Metafields To Shopify"; Rec."Company Metafields To Shopify") { diff --git a/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al b/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al index 8b29c15807..f299ce88d8 100644 --- a/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al +++ b/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al @@ -757,6 +757,19 @@ table 30102 "Shpfy Shop" Caption = 'Auto Create Catalog'; ToolTip = 'Specifies whether a catalog is automatically created for new companies.'; DataClassification = CustomerContent; + + trigger OnValidate() + var + ErrorInfo: ErrorInfo; + begin + if Rec."Auto Create Catalog" and not Rec."Advanced Shopify Plan" then begin + ErrorInfo.FieldNo(Rec.FieldNo("Auto Create Catalog")); + ErrorInfo.ErrorType := ErrorType::Client; + ErrorInfo.RecordId := Rec.RecordId; + ErrorInfo.Message := StrSubstNo(AutoCreateCatalogPlanErr, Rec.FieldCaption("Auto Create Catalog")); + Error(ErrorInfo); + end; + end; } field(121; "Company Import From Shopify"; Enum "Shpfy Company Import Range") { @@ -981,6 +994,7 @@ table 30102 "Shpfy Shop" var CurrencyExchangeRateNotDefinedErr: Label 'The specified currency must have exchange rates configured. If your online shop uses the same currency as Business Central then leave the field empty.'; AutoCreateErrorMsg: Label 'You cannot turn "%1" off if "%2" is set to the value of "%3".', Comment = '%1 = Field Caption of "Auto Create Orders", %2 = Field Caption of "Return and Refund Process", %3 = Field Value of "Return and Refund Process"'; + AutoCreateCatalogPlanErr: Label '%1 can only be enabled for Shopify Plus, Plus Trial, Development, or Advanced plans.', Comment = '%1 = Field Caption of "Auto Create Catalog"'; ExpirationNotificationTxt: Label 'Shopify API version 30 days before expiry notification sent.', Locked = true; BlockedNotificationTxt: Label 'Shopify API version expired notification sent.', Locked = true; CategoryTok: Label 'Shopify Integration', Locked = true; diff --git a/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al index a3c44df414..23885756d7 100644 --- a/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al +++ b/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al @@ -59,6 +59,33 @@ codeunit 139551 "Shpfy Staff Test" ShpfyShopCard.Close(); end; + [Test] + procedure TestAutoCreateCatalogRequiresAdvancedPlan() + var + LibraryAssert: Codeunit "Library Assert"; + begin + // [Given] A shop on a plan that does not support B2B catalogs + Initialize(); + Shop."Advanced Shopify Plan" := false; + Shop."Auto Create Catalog" := false; + Shop.Modify(false); + + // [When] The user tries to enable Auto Create Catalog + // [Then] A field error is raised mentioning the field + asserterror Shop.Validate("Auto Create Catalog", true); + LibraryAssert.ExpectedError('Auto Create Catalog'); + + // [Given] The shop is upgraded to a plan that supports B2B catalogs + Shop."Advanced Shopify Plan" := true; + Shop.Modify(false); + + // [When] The user enables Auto Create Catalog + Shop.Validate("Auto Create Catalog", true); + + // [Then] The field is enabled successfully + LibraryAssert.IsTrue(Shop."Auto Create Catalog", 'Auto Create Catalog should be enabled on an Advanced plan.'); + end; + [Test] [HandlerFunctions('HttpSubmitHandler')] procedure TestImportStaff() From 40bf59a5a8c316828834edf54a1ea303afa4e3bd Mon Sep 17 00:00:00 2001 From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com> Date: Tue, 19 May 2026 21:54:46 +0200 Subject: [PATCH 2/3] Address PR review: simplify error + handle plan downgrade - Simplify the Auto Create Catalog OnValidate to use Error() with a StrSubstNo-style label instead of the heavier ErrorInfo pattern. - Close the plan-downgrade gap flagged in PR review: GetShopSettings() now calls Rec.Validate("Advanced Shopify Plan", ...) instead of direct assignment, and field 207 has an OnValidate that auto-disables Auto Create Catalog (with a user message) when the plan is downgraded. Without the Validate switch the bot's suggested OnValidate would never fire from the actual API-sync path. - Add TestAdvancedPlanDowngradeDisablesAutoCreateCatalog covering the downgrade path and a small MessageHandler. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../App/src/Base/Tables/ShpfyShop.Table.al | 24 ++++++++++--------- .../Test/Staff/ShpfyStaffTest.Codeunit.al | 24 +++++++++++++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al b/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al index f299ce88d8..130300cc7c 100644 --- a/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al +++ b/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al @@ -759,16 +759,9 @@ table 30102 "Shpfy Shop" DataClassification = CustomerContent; trigger OnValidate() - var - ErrorInfo: ErrorInfo; begin - if Rec."Auto Create Catalog" and not Rec."Advanced Shopify Plan" then begin - ErrorInfo.FieldNo(Rec.FieldNo("Auto Create Catalog")); - ErrorInfo.ErrorType := ErrorType::Client; - ErrorInfo.RecordId := Rec.RecordId; - ErrorInfo.Message := StrSubstNo(AutoCreateCatalogPlanErr, Rec.FieldCaption("Auto Create Catalog")); - Error(ErrorInfo); - end; + if Rec."Auto Create Catalog" and not Rec."Advanced Shopify Plan" then + Error(AutoCreateCatalogPlanErr, Rec.FieldCaption("Auto Create Catalog")); end; } field(121; "Company Import From Shopify"; Enum "Shpfy Company Import Range") @@ -955,6 +948,14 @@ table 30102 "Shpfy Shop" { Caption = 'Advanced Shopify Plan'; DataClassification = SystemMetadata; + + trigger OnValidate() + begin + if (not Rec."Advanced Shopify Plan") and Rec."Auto Create Catalog" then begin + Rec.Validate("Auto Create Catalog", false); + Message(AutoCreateCatalogDisabledMsg); + end; + end; } field(208; "Find Mapping by Barcode"; Boolean) { @@ -995,6 +996,7 @@ table 30102 "Shpfy Shop" CurrencyExchangeRateNotDefinedErr: Label 'The specified currency must have exchange rates configured. If your online shop uses the same currency as Business Central then leave the field empty.'; AutoCreateErrorMsg: Label 'You cannot turn "%1" off if "%2" is set to the value of "%3".', Comment = '%1 = Field Caption of "Auto Create Orders", %2 = Field Caption of "Return and Refund Process", %3 = Field Value of "Return and Refund Process"'; AutoCreateCatalogPlanErr: Label '%1 can only be enabled for Shopify Plus, Plus Trial, Development, or Advanced plans.', Comment = '%1 = Field Caption of "Auto Create Catalog"'; + AutoCreateCatalogDisabledMsg: Label 'Auto Create Catalog has been disabled because the Shopify plan no longer supports B2B catalog creation.'; ExpirationNotificationTxt: Label 'Shopify API version 30 days before expiry notification sent.', Locked = true; BlockedNotificationTxt: Label 'Shopify API version expired notification sent.', Locked = true; CategoryTok: Label 'Shopify Integration', Locked = true; @@ -1157,8 +1159,8 @@ table 30102 "Shpfy Shop" JResponse := CommunicationMgt.ExecuteGraphQL('{"query":"query { shop { name plan { publicDisplayName partnerDevelopment shopifyPlus } weightUnit } }"}'); if JResponse.SelectToken('$.data.shop.plan', JItem) then if JItem.IsObject then - Rec."Advanced Shopify Plan" := JsonHelper.GetValueAsBoolean(JItem, 'shopifyPlus') or - (JsonHelper.GetValueAsText(JItem, 'publicDisplayName') in ['Plus Trial', 'Development', 'Advanced']); + Rec.Validate("Advanced Shopify Plan", JsonHelper.GetValueAsBoolean(JItem, 'shopifyPlus') or + (JsonHelper.GetValueAsText(JItem, 'publicDisplayName') in ['Plus Trial', 'Development', 'Advanced'])); Rec."Weight Unit" := ConvertToWeightUnit(JsonHelper.GetValueAsText(JResponse, 'data.shop.weightUnit')); end; diff --git a/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al index 23885756d7..9512fd673d 100644 --- a/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al +++ b/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al @@ -86,6 +86,25 @@ codeunit 139551 "Shpfy Staff Test" LibraryAssert.IsTrue(Shop."Auto Create Catalog", 'Auto Create Catalog should be enabled on an Advanced plan.'); end; + [Test] + [HandlerFunctions('AutoCreateCatalogDisabledMessageHandler')] + procedure TestAdvancedPlanDowngradeDisablesAutoCreateCatalog() + var + LibraryAssert: Codeunit "Library Assert"; + begin + // [Given] A shop on an Advanced plan with Auto Create Catalog enabled + Initialize(); + Shop."Advanced Shopify Plan" := true; + Shop."Auto Create Catalog" := true; + Shop.Modify(false); + + // [When] The shop's plan is downgraded (as happens during a plan sync from Shopify) + Shop.Validate("Advanced Shopify Plan", false); + + // [Then] Auto Create Catalog is automatically disabled and the user is notified via the message handler + LibraryAssert.IsFalse(Shop."Auto Create Catalog", 'Auto Create Catalog should be disabled after the plan is downgraded.'); + end; + [Test] [HandlerFunctions('HttpSubmitHandler')] procedure TestImportStaff() @@ -294,6 +313,11 @@ codeunit 139551 "Shpfy Staff Test" exit(false); // Prevents actual HTTP call end; + [MessageHandler] + internal procedure AutoCreateCatalogDisabledMessageHandler(Message: Text[1024]) + begin + end; + local procedure MakeResponse(var HttpResponseMessage: TestHttpResponseMessage): Boolean begin LoadResourceIntoHttpResponse(ResponseResourceUrl, HttpResponseMessage); From 6f0ad8b1ba3c8e22d9a547c7f3b224e04c77d7a1 Mon Sep 17 00:00:00 2001 From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com> Date: Tue, 19 May 2026 22:30:10 +0200 Subject: [PATCH 3/3] Drop user-facing message on plan downgrade Silently disable Auto Create Catalog when Advanced Shopify Plan is turned off; remove the now-unused label and test MessageHandler. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al | 5 +---- src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al | 8 +------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al b/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al index 130300cc7c..98ca1a33a4 100644 --- a/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al +++ b/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al @@ -951,10 +951,8 @@ table 30102 "Shpfy Shop" trigger OnValidate() begin - if (not Rec."Advanced Shopify Plan") and Rec."Auto Create Catalog" then begin + if (not Rec."Advanced Shopify Plan") and Rec."Auto Create Catalog" then Rec.Validate("Auto Create Catalog", false); - Message(AutoCreateCatalogDisabledMsg); - end; end; } field(208; "Find Mapping by Barcode"; Boolean) @@ -996,7 +994,6 @@ table 30102 "Shpfy Shop" CurrencyExchangeRateNotDefinedErr: Label 'The specified currency must have exchange rates configured. If your online shop uses the same currency as Business Central then leave the field empty.'; AutoCreateErrorMsg: Label 'You cannot turn "%1" off if "%2" is set to the value of "%3".', Comment = '%1 = Field Caption of "Auto Create Orders", %2 = Field Caption of "Return and Refund Process", %3 = Field Value of "Return and Refund Process"'; AutoCreateCatalogPlanErr: Label '%1 can only be enabled for Shopify Plus, Plus Trial, Development, or Advanced plans.', Comment = '%1 = Field Caption of "Auto Create Catalog"'; - AutoCreateCatalogDisabledMsg: Label 'Auto Create Catalog has been disabled because the Shopify plan no longer supports B2B catalog creation.'; ExpirationNotificationTxt: Label 'Shopify API version 30 days before expiry notification sent.', Locked = true; BlockedNotificationTxt: Label 'Shopify API version expired notification sent.', Locked = true; CategoryTok: Label 'Shopify Integration', Locked = true; diff --git a/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al index 9512fd673d..61a72d2a69 100644 --- a/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al +++ b/src/Apps/W1/Shopify/Test/Staff/ShpfyStaffTest.Codeunit.al @@ -87,7 +87,6 @@ codeunit 139551 "Shpfy Staff Test" end; [Test] - [HandlerFunctions('AutoCreateCatalogDisabledMessageHandler')] procedure TestAdvancedPlanDowngradeDisablesAutoCreateCatalog() var LibraryAssert: Codeunit "Library Assert"; @@ -101,7 +100,7 @@ codeunit 139551 "Shpfy Staff Test" // [When] The shop's plan is downgraded (as happens during a plan sync from Shopify) Shop.Validate("Advanced Shopify Plan", false); - // [Then] Auto Create Catalog is automatically disabled and the user is notified via the message handler + // [Then] Auto Create Catalog is silently disabled LibraryAssert.IsFalse(Shop."Auto Create Catalog", 'Auto Create Catalog should be disabled after the plan is downgraded.'); end; @@ -313,11 +312,6 @@ codeunit 139551 "Shpfy Staff Test" exit(false); // Prevents actual HTTP call end; - [MessageHandler] - internal procedure AutoCreateCatalogDisabledMessageHandler(Message: Text[1024]) - begin - end; - local procedure MakeResponse(var HttpResponseMessage: TestHttpResponseMessage): Boolean begin LoadResourceIntoHttpResponse(ResponseResourceUrl, HttpResponseMessage);