Skip to content

[Shopify] Skip refund credit memo while transaction is pending#9112

Merged
onbuyuka merged 3 commits into
mainfrom
bugs/640432-shpfy-refund-pending-transaction-crmemo
Jul 9, 2026
Merged

[Shopify] Skip refund credit memo while transaction is pending#9112
onbuyuka merged 3 commits into
mainfrom
bugs/640432-shpfy-refund-pending-transaction-crmemo

Conversation

@onbuyuka

@onbuyuka onbuyuka commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Fixes AB#640432

Summary

When a Shopify refund is synced while its payment transaction is still pending, Shopify's totalRefundedSet returns 0 (it only counts SUCCESS transactions). If a credit memo is created at that moment, the balancing line in CreateSalesLinesFromRemainingAmount calculates Unit Price = 0 - <item total>, producing a credit memo whose total is 0 — a financially useless document.

Root cause

ShpfyCreateSalesDocRefund.Codeunit.al balances the document against RefundHeader."Total Refunded Amount", which is 0 while the refund transaction is still pending, even though the item/return lines already sum to the real amount.

Fix

Block credit memo / return order creation while the refund still has a pending transaction, mirroring the existing "Can Create Credit Memo" dual-guard pattern:

  • ShpfyRefundsAPI.Codeunit.al — new internal helper HasPendingRefundTransactions(RefundId) that checks for refund transactions with Type = Refund and Status = Pending. VerifyRefundCanCreateCreditMemo now throws a clear error when a pending transaction exists (manual Create Sales Document path).
  • ShpfyRetRefProcCrMemo.Codeunit.alCreateSalesDocument now exits early (silent skip) when the refund still has a pending transaction (auto-sync path). The refund stays unprocessed and is retried on the next sync; once the transaction reaches SUCCESS, totalRefundedSet is final and the credit memo is created correctly.

This is safe because the auto-processing loop (ProcessShopifyRefunds) retries all unprocessed refunds on every sync, and no data is guessed or approximated.

Test plan

Added to ShpfyOrderRefundTest.Codeunit.al (with a CreateRefundTransaction helper in ShpfyOrderRefundsHelper.Codeunit.al):

  • UnitTestDoesNotCreateCrMemoFromRefundWithPendingTransaction — no credit memo is created while the refund has a pending transaction.
  • UnitTestCreatesCrMemoFromRefundWithSucceededTransaction — the guard is specific to pending; a succeeded transaction still creates the credit memo.
  • UnitTestVerifyRefundCanCreateCreditMemoErrorsWithPendingTransaction — the manual path throws the pending-transaction error.

When a Shopify refund is synced while its payment transaction is still pending, Shopify's totalRefundedSet returns 0, so the balancing line calculation produced a credit memo that zeroed out to a total of 0. This blocks credit memo/return order creation while the refund still has a pending transaction: the auto-sync path skips it silently and retries on the next sync (once the transaction succeeds), and the manual Create Sales Document path shows a clear error. Adds a HasPendingRefundTransactions helper plus tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@onbuyuka
onbuyuka requested a review from a team July 6, 2026 08:20
@github-actions github-actions Bot added the AL: Apps (W1) Add-on apps for W1 label Jul 6, 2026
@github-actions github-actions Bot added this to the Version 29.0 milestone Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Copilot PR Review

Iteration 3 · Outcome: completed

All applicable sub-skills completed; al-ui-review was not-applicable (no page or control add-in files in the diff). Self-review pass found no cross-cutting defect clearing the agent-finding precision bar.

Knowledge source: https://github.com/microsoft/BCQuality@822cae1b2771ac25f665f73369f69093bd4fd630

Orchestrator pre-filter (13 file(s) excluded)

  • layer-disabled (knowledge) : 13 file(s)

Findings produced by the Copilot CLI agent against BCQuality at 822cae1b2771ac25f665f73369f69093bd4fd630. Reply 👎 on any inline comment to flag false positives.

…lookup

HasPendingRefundTransactions (and the pre-existing MapPaymentMethodCode / GetRoundingAmountFromTransactions) filter Shpfy Order Transaction by Refund Id, but no key had Refund Id as a leading field, forcing a scan on a table that grows unbounded. Add key (Refund Id, Type, Status) covering all three call sites and set it explicitly in HasPendingRefundTransactions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@onbuyuka
onbuyuka enabled auto-merge July 6, 2026 08:40
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@onbuyuka
onbuyuka added this pull request to the merge queue Jul 9, 2026
Merged via the queue into main with commit a640b3d Jul 9, 2026
328 of 330 checks passed
@onbuyuka
onbuyuka deleted the bugs/640432-shpfy-refund-pending-transaction-crmemo branch July 9, 2026 12:27
onbuyuka added a commit that referenced this pull request Jul 23, 2026
Fixes
[AB#640432](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/640432)

When a Shopify refund is synced while its payment transaction is still
**pending**, Shopify's `totalRefundedSet` returns 0 (it only counts
`SUCCESS` transactions). If a credit memo is created at that moment, the
balancing line in `CreateSalesLinesFromRemainingAmount` calculates `Unit
Price = 0 - <item total>`, producing a credit memo whose total is 0 — a
financially useless document.

`ShpfyCreateSalesDocRefund.Codeunit.al` balances the document against
`RefundHeader."Total Refunded Amount"`, which is 0 while the refund
transaction is still pending, even though the item/return lines already
sum to the real amount.

Block credit memo / return order creation while the refund still has a
pending transaction, mirroring the existing `"Can Create Credit Memo"`
dual-guard pattern:

- **`ShpfyRefundsAPI.Codeunit.al`** — new internal helper
`HasPendingRefundTransactions(RefundId)` that checks for refund
transactions with `Type = Refund` and `Status = Pending`.
`VerifyRefundCanCreateCreditMemo` now throws a clear error when a
pending transaction exists (manual **Create Sales Document** path).
- **`ShpfyRetRefProcCrMemo.Codeunit.al`** — `CreateSalesDocument` now
exits early (silent skip) when the refund still has a pending
transaction (auto-sync path). The refund stays unprocessed and is
retried on the next sync; once the transaction reaches `SUCCESS`,
`totalRefundedSet` is final and the credit memo is created correctly.

This is safe because the auto-processing loop (`ProcessShopifyRefunds`)
retries all unprocessed refunds on every sync, and no data is guessed or
approximated.

Added to `ShpfyOrderRefundTest.Codeunit.al` (with a
`CreateRefundTransaction` helper in
`ShpfyOrderRefundsHelper.Codeunit.al`):

- `UnitTestDoesNotCreateCrMemoFromRefundWithPendingTransaction` — no
credit memo is created while the refund has a pending transaction.
- `UnitTestCreatesCrMemoFromRefundWithSucceededTransaction` — the guard
is specific to pending; a succeeded transaction still creates the credit
memo.
- `UnitTestVerifyRefundCanCreateCreditMemoErrorsWithPendingTransaction`
— the manual path throws the pending-transaction error.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b1f006ac-3ace-495d-8b5c-9b76510cf117
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.

3 participants