Skip to content

[releases/27.x] [Shopify] API 2026-01 uptake (#6244)#8360

Open
onbuyuka wants to merge 7 commits into
releases/27.xfrom
features/621974-shopify-api-2026-01-uptake
Open

[releases/27.x] [Shopify] API 2026-01 uptake (#6244)#8360
onbuyuka wants to merge 7 commits into
releases/27.xfrom
features/621974-shopify-api-2026-01-uptake

Conversation

@onbuyuka
Copy link
Copy Markdown
Contributor

@onbuyuka onbuyuka commented May 27, 2026

Backport of #6244 to releases/27.x as part of slice 621974.

Fixes AB#617321

Commits included

Commit Source PR Rationale
29fe94d #4747 Prerequisite — Import unverified returns. The API 2026-01 uptake builds on top of this.
25f5fa3 #6244 API 2026-01 uptake — main change.
24b1fa3 #7214 Direct follow-up to #6244: skip empty inventory API call when batch size is exact multiple of 250. Fixes a boundary bug in the new 50K-batching code added by the uptake.
be6ef87 #8309 Direct follow-up to #6244: fix wrong dictionary used for pagination cursor in ShpfyReturnsAPI. The file was substantially rewritten by the uptake.
7820cf1 (new) Bump App/app.json idRanges.to from 30450 → 30460 to accommodate new codeunit 30457 from #6244.

Scope rationale

The 17 commits that touch any file modified by #6244 since it merged were triaged. Only #7214 and #8309 are direct API-2026-01 follow-ups (fix bugs in code introduced or substantially rewritten by the uptake). All other overlap commits are independent features, refactors, version bumps, already-backported fixes, or coincidental file overlaps — explicitly excluded to keep this backport low-risk.

Notably excluded: PR #7204 (IsTestInProgressHttpClientHandler test-infra migration) and PR #6396 (Inventory Sync Controls feature) — both are out-of-scope and not API-version-related.

Conflict resolution

The uptake cherry-pick had 5 conflicts caused by PR #7633 (multi-store payout fix) already being backported to releases/27.x as commit 18ad26aae. All conflict hunks were resolved by preferring the uptake's content where it modifies the same lines, while preserving the multi-store fix elsewhere.

PR #7214 cherry-pick dropped two ForceExport-dependent test assertions that require PR #6396 (excluded from this backport).

onbuyuka and others added 5 commits May 27, 2026 18:36
<!-- Thank you for submitting a Pull Request. If you're new to
contributing to BCApps please read our pull request guideline below
* https://github.com/microsoft/BCApps/Contributing.md
-->
#### Summary <!-- Provide a general summary of your changes -->
Complicated process...
https://help.shopify.com/en/manual/sell-in-person/shopify-pos/order-management/unverified-returns
So far we are only going to import them and that's it. We may think
about creating ledger entries to balance the inventory, customer account
etc. but not now

#### Work Item(s) <!-- Add the issue number here after the #. The issue
needs to be open and approved. Submitting PRs with no linked issues or
unapproved issues is highly discouraged. -->
Fixes
[AB#601701](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/601701)
This PR upgrades the Shopify Connector to API version 2026-01,
addressing deprecations, new features, and breaking changes announced in
the Shopify changelog.

- **Mutation upgrade**: Replaced deprecated
`inventorySetOnHandQuantities` with `inventorySetQuantities` using
`name: "on_hand"` and `reason: "correction"`
- **Idempotency support**: Added `@idempotent(key: "...")` directive to
inventory mutations for safe retries
- **Concurrency handling**: Added `changeFromQuantity: null` to opt-out
of compare-and-swap (BC is the authoritative source)
- **Retry logic**: Auto-retry once on `IDEMPOTENCY_CONCURRENT_REQUEST`
or `CHANGE_FROM_QUANTITY_STALE` errors, then log to skipped records

- Added batching logic in `AddProductVariants` to respect the new limit
of 50,000 inventory quantities per mutation
- `GetMaxVariantsPerBatch()` calculates max variants based on `50000 div
LocationCount`
- Made `GetDefaultLocationCount()` and `GetMaxVariantsPerBatch()`
internal for testability

- Removed deprecated `currentBulkOperation` query (now uses
`GetBulkRequest` by ID)
- Deleted `ShpfyGQLBulkOperations.Codeunit.al` and removed
`GetCurrentBulkOperation` enum value

- Replaced deprecated `returnReason` enum with `returnReasonDefinition {
name handle }`
- Added `Return Reason Name` and `Return Reason Handle` fields to `Shpfy
Return Line` table
- Marked old `Return Reason` enum field as obsolete

- Added `externalTraceId` field to payout queries and `Shpfy Payout`
table
- Made `ImportPayout()` internal for testability

- Removed deprecated `taxCode` field from variant queries and mutations
- Marked `Tax Code` field as obsolete on `Shpfy Variant` table and page

- Added `article_reference` metafield type with
`ShpfyMtfldTypeArticleRef.Codeunit.al`

- **New**: ShpfyInventoryExportTest.Codeunit.al - Tests for idempotency,
retry logic, and skipped record logging
- **New**: ShpfyInventorySubscriber.Codeunit.al - Mock subscriber with
configurable retry scenarios
- **New**: ShpfyInventoryRetryScenario.Enum.al - Enum for test scenarios
(Success, FailOnceThenSucceed, AlwaysFail)
- **New**: ShpfyVariantBatchingTest.Codeunit.al - Tests for 50K limit
batch calculations
- **Updated**: ShpfyOrderRefundsHelper.Codeunit.al - Uses new return
reason fields
- **Updated**: ShpfyPaymentsTest.Codeunit.al - Added `externalTraceId`
test
- **Updated**: ShpfyBulkOpSubscriber.Codeunit.al - Removed obsolete
`currentBulkOperation` handler
- **Deleted**: CurrentBulkOperationCompletedResult.txt,
CurrentBulkOperationRunningResult.txt

- `inventorySetOnHandQuantities` mutation replaced - no action required
for users
- `returnReason` field deprecated - users should reference `Return
Reason Name` instead
- `taxCode` field deprecated - users relying on this field should
migrate away

- [Shopify API 2026-01
Changelog](https://shopify.dev/changelog?filter=api&api_version=2026-01&api_type=admin-graphql)
- [Shopify API 2025-10
Changelog](https://shopify.dev/changelog?filter=api&api_version=2025-10&api_type=admin-graphql)

Fixes
[AB#617321](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/617321)
…iple of 250 (#7214)

- Guard the final `ExecuteInventoryGraphQL` call in `ExportStock` with
`if InputSize > 0` to avoid sending an unnecessary empty request when
the number of inventory items is an exact multiple of the 250-item batch
size

Fixes
[AB#625960](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/625960)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…PI (#8309)

## What this changes

In Shpfy Returns API (codeunit 30250), procedures GetReturnLocations
(lines 107–130) and GetReturnLocationsFromReturnFulfillOrder (lines
132–155) both declare a local `LineParameters: Dictionary of [text,
Text]` and pass that dictionary to `CommunicationMgt.ExecuteGraphQL` —
but they were writing the `After` cursor into the **module-level**
`Parameters` dictionary instead.

As a result the `{{After}}` placeholder in
`GetNextReverseFulfillmentOrders.graphql` and
`GetNextReverseFulfillmentOrderLines.graphql` (both substituted from
`LineParameters`) was never populated, breaking pagination beyond the
first 10 reverse-fulfillment-orders for a return, or the first 10 line
items of a reverse fulfillment order.

The user-visible symptom is **Shpfy Return Lines with missing Location
IDs**, and credit memos that consequently lose the restock-to-location
information for the affected lines. The intermittence depends on whether
a return reaches the >10 reverse-fulfillment-orders or >10 lines-per-RFO
thresholds.

This PR replaces the three `Parameters` references in each procedure
with `LineParameters` — the dictionary that is actually passed to
`ExecuteGraphQL`. Six lines changed total.

## Why no test

There is no existing unit-test coverage for `GetReturnLocations` /
`GetReturnLocationsFromReturnFulfillOrder` in
`src/Apps/W1/Shopify/Test`. A pagination test would need new
mock-GraphQL fixtures that simulate the `pageInfo.hasNextPage` contract
for the `reverseFulfillmentOrders` connection and a multi-page
disposition response. That harness work is out of scope for this
surgical fix; a follow-up to add coverage is welcome.

Fixes
[AB#636657](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/636657)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>


Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@onbuyuka onbuyuka requested review from a team as code owners May 27, 2026 16:53
@github-actions github-actions Bot added the AL: Apps (W1) Add-on apps for W1 label May 27, 2026
onbuyuka and others added 2 commits May 27, 2026 19:47
On main, the backfill test added by PR #7633 reuses the 2-arg GetRandomPayout(Id, ExternalTraceId) helper introduced by the API 2026-01 uptake (PR #6244), passing a throwaway value for the externalTraceId. On releases/27.x #7633 was backported before the uptake, so the cherry-pick produced two overloaded GetRandomPayout procedures, each with a local 'PayoutGidTxt' Label. AL's translation ID derivation collapses overloads, triggering AL0570.

Mirror main: drop the 1-arg overload and have UnitTestImportPayoutBackfillsShopCode call the 2-arg helper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ring

Reorder so UnitTestImportPayoutWithExternalTraceId runs before
UnitTestImportPayoutBackfillsShopCode and add Initialize()/SetShop(Shop)
plus Shop Code assertion to ExternalTraceId test. Matches the structure
on main (post #7633), avoiding cross-test 'Any' codeunit and DB state
leakage that caused the External Trace Id assertion to fail on 27.x.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AL: Apps (W1) Add-on apps for W1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant