[Shopify] Refresh cached plan before order sync#8212
Conversation
Auto-refresh Shop."Advanced Shopify Plan" via the existing Shop.GetShopSettings() helper before both order-import entry points so that a Shopify plan downgrade doesn't leave the connector requesting the staffMember field that the new plan can no longer grant access to (ACCESS_DENIED on read_users scope). Entry points covered: - Bulk sync: report 30104 "Shpfy Sync Orders from Shopify" (also the scheduled auto-sync path). One refresh call per shop per batch run. - Single-order reimport: ShpfyImportOrder .ReimportExistingOrderConfirmIfConflicting. Tests added to ShpfyOrdersAPITest.Codeunit.al: - TestGetShopSettingsClearsStaleAdvancedShopifyPlanFlag - TestSyncOrdersFromShopifyReportRefreshesAdvancedShopifyPlanFlag Fixes AB#635878 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Address PR review feedback: reset PlanRefreshExpected / PlanRefreshCallCount at the start of Initialize() so an assertion failure in one test cannot leak the plan-refresh flag into the next test and corrupt unrelated HTTP calls. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Unhandled API failure can abort entire report
Recommendation:
Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
…eunit.al Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
| OrderHeader.Get(OrderHeader."Shopify Order Id"); | ||
| if ShopToRefresh.Get(OrderHeader."Shop Code") then begin | ||
| ShopToRefresh.GetShopSettings(); | ||
| ShopToRefresh.Modify(); |
There was a problem hiding this comment.
Modify() runs OnModify trigger unintentionally
ShopToRefresh.Modify() without false fires the OnModify table trigger on the Shpfy Shop record. The only intent is to persist the refreshed plan settings returned by GetShopSettings(); triggering the full modify business logic is an unintended side effect.
Recommendation:
- Pass
falseto suppress the trigger:ShopToRefresh.Modify(false);
| ShopToRefresh.Modify(); | |
| if ShopToRefresh.Get(OrderHeader."Shop Code") then begin | |
| ShopToRefresh.GetShopSettings(); | |
| ShopToRefresh.Modify(false); | |
| end; |
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why
| trigger OnAfterGetRecord() | ||
| begin | ||
| Shop.GetShopSettings(); | ||
| Shop.Modify(); |
There was a problem hiding this comment.
Modify() runs OnModify trigger unintentionally
Shop.Modify() without a false argument defaults to RunTrigger := true, which fires the OnModify table trigger on every shop record the report iterates. The intent here is only to persist the settings fetched by GetShopSettings(); triggering business logic in OnModify may cause unintended side effects or duplicate work.
Recommendation:
- Pass
falseto suppress the trigger:Shop.Modify(false);
| Shop.Modify(); | |
| Shop.GetShopSettings(); | |
| Shop.Modify(false); |
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why
Summary
Bug 635878: When a merchant downgrades their Shopify plan from Plus / Advanced to a standard plan, the connector keeps requesting the
staffMember { id }field in the order GraphQL query. The lower plan does not grantread_usersscope, so Shopify returnsACCESS_DENIEDand order sync is fully broken until the user manually toggles the Enabled field off and on again on the Shop Card.Shop."Advanced Shopify Plan"(field 207) is the cached flag that gates the staff member field. It was only refreshed when the user toggled Enabled or when a scope change was detected on Shop Card open — never before an order sync.Fix
Auto-refresh the cached plan via the existing
Shop.GetShopSettings()helper (one cheap GraphQL query forshop { plan { ... } weightUnit }) before both order-import entry points:30104 Shpfy Sync Orders from Shopify(also the scheduled auto-sync path). One refresh call per shop per batch run.ShpfyImportOrder.ReimportExistingOrderConfirmIfConflicting(manual reimport action on the Order Header page).The refresh is deliberately not placed in
ShpfyImportOrder.SetShop()because that runs per order; for a 100-order batch it would mean 100 extra GraphQL round-trips.Tests
Two regression tests added to the existing
ShpfyOrdersAPITest.Codeunit.al(139608):TestGetShopSettingsClearsStaleAdvancedShopifyPlanFlag— sets stale"Advanced Shopify Plan" = true, callsGetShopSettings, asserts the flag becomesfalse.TestSyncOrdersFromShopifyReportRefreshesAdvancedShopifyPlanFlag— sets stale flag, runs Report 30104, asserts the persisted Shop record has the flag refreshed tofalse.Existing
OrdersAPIHttpHandlerextended with a one-shotPlanRefreshExpectedflag returning a downgraded-plan JSON for the first request, then falling through to the prior empty-data behavior.Both tests verified locally.
Fixes AB#635878