Skip to content

[Shopify] Fix #7724: Resolve Option 1 Name from existing Shopify Variant records#8577

Open
tVisionDeb wants to merge 1 commit into
microsoft:mainfrom
tVisionDeb:fix/7724-shopify-variant-option-name
Open

[Shopify] Fix #7724: Resolve Option 1 Name from existing Shopify Variant records#8577
tVisionDeb wants to merge 1 commit into
microsoft:mainfrom
tVisionDeb:fix/7724-shopify-variant-option-name

Conversation

@tVisionDeb

@tVisionDeb tVisionDeb commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #7724 - regression introduced in PR #7660 where Option 1 Name was being reset to 'Variant' for Shopify-origin products whose variants already have a different Option 1 Name (e.g. 'Color', 'Size', etc.).

Root Cause

In FillInProductVariantData, after resolving the Option 1 Name from existing Shopify variant records, the code failed to set Option 1 Value when the resolved name was anything other than 'Variant'. The guard condition was missing the JustResolvedOption1Name flag.

Fix

Added a JustResolvedOption1Name boolean so that Option 1 Value is always set when the name was just resolved from Shopify - regardless of what the resolved name is (e.g. 'Color', 'Size', 'Variant', etc.).

Tests Added

New test codeunit 139649 - Shpfy Variant Option1Name Test with 5 scenarios:

  1. UnitTestOption1NameInheritedFromShopifyOriginProduct - Shopify-origin product with existing variants keeps their Option 1 Name and sets Option 1 Value correctly
  2. UnitTestOption1NameDefaultsToVariantForBCOriginProduct - BC-origin product (no existing Shopify variants) gets 'Variant' as Option 1 Name
  3. UnitTestOption1NameDefaultsToVariantWhenNoExistingVariants - No existing variants defaults to 'Variant'
  4. UnitTestOption1NameDefaultsToVariantWhenAmbiguous - Ambiguous case (multiple different Option 1 Names) defaults to 'Variant'
  5. UnitTestOption1NameAndValuePreservedOnUpdatePath - Update path: pre-existing Option 1 Name is preserved and Option 1 Value is set correctly

All 5 new tests pass locally on BC v29. Existing codeunit 139601 (Product Export) also passes - no regression introduced.

…pify Variant records

- FillInProductVariantData(ShopifyVariant, Item, ItemVariant): resolve Option 1 Name
  from existing Shpfy Variant rows for the product when the field is blank, falling
  back to 'Variant' when no rows exist or names are inconsistent.
- Added JustResolvedOption1Name guard so Option 1 Value is only overwritten on the
  create path (blank Option 1 Name resolved, or existing placeholder 'Variant').
  Existing Shopify-origin variants with a real Option 1 Name (e.g. 'Color') now
  keep their Option 1 Value on the update path, preventing silent data corruption.
- Added codeunit 139649 Shpfy Variant Option1 Name Test covering all 5 scenarios
  from issue microsoft#7724: Shopify-origin inherit, BC-origin unchanged, no-variants fallback,
  ambiguous fallback, and update-path preservation.
@tVisionDeb tVisionDeb requested a review from a team as a code owner June 10, 2026 20:45
@tVisionDeb

Copy link
Copy Markdown
Contributor Author

Hi @onbuyuka - thank you for the thorough review on the previous PR (#8048). I have addressed all your feedback:

Changes made:

  1. JustResolvedOption1Name guard - The fix now correctly sets Option 1 Value whenever the name was just resolved from Shopify (regardless of the resolved value), not just when the name is literally 'Variant'.

  2. ResolveOption1Name procedure - Extracted into a clean local procedure ResolveOption1Name(ProductId: BigInteger): Text[50] that queries existing Shpfy Variant records for the product and returns the common name if unambiguous, or falls back to 'Variant'.

  3. Test coverage - Added new test codeunit 139649 "Shpfy Variant Option1Name Test" with 5 test methods covering all the cases discussed in the review:

    • Shopify-origin product inherits Option 1 Name from existing variants
    • BC-origin product defaults to 'Variant'
    • No existing variants defaults to 'Variant'
    • Ambiguous (conflicting names) defaults to 'Variant'
    • Update path preserves existing name and sets value correctly

Local test results (BC v29 container):

  • Codeunit 139649 (new tests): PASSED (all 5 tests)
  • Codeunit 139601 (existing Product Export tests): PASSED (no regression)

Ready for re-review.

@github-actions github-actions Bot added AL: Apps (W1) Add-on apps for W1 From Fork Pull request is coming from a fork needs-approval Workflow runs require maintainer approval to start labels Jun 10, 2026
end;
if ShopifyVariant."Option 1 Name" = '' then
ShopifyVariant."Option 1 Name" := 'Variant';
if ShopifyVariant."Option 1 Name" = 'Variant' then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Performance} \quad \color{gray}{\texttt{\small Iteration\ 1}}$

Uncached DB read per variant export in ResolveOption1Name

ResolveOption1Name executes a full FindSet() on Shpfy Variant every time FillInProductVariantData is called with a blank Option 1 Name. For a product with N blank-name variants being exported in a single run, this produces N redundant database reads returning the same result for the same Product ID.

Recommendation:

  • Cache the resolved name at the product level before iterating over variants, e.g. compute it once per product and pass it in, or use a local dictionary keyed by Product ID within the calling loop.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

VariantOption1Name: Text[50];
FirstVariantName: Boolean;
begin
ShpfyVariant.SetRange("Product Id", ProductId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟠\ High\ Severity\ —\ Security} \quad \color{gray}{\texttt{\small Iteration\ 1}}$

Missing shop code filter in ResolveOption1Name

ResolveOption1Name filters Shpfy Variant only by 'Product Id', ignoring 'Shop Code'. In a multi-shop deployment, a variant from a different shop that happens to share the same numeric Product ID would be included in the lookup, potentially returning that shop's Option 1 Name for the wrong shop's product.

Recommendation:

  • Add a shop code filter before FindSet(). Pass the shop code as a parameter (or read it from the existing ShopifyVariant record that is already in scope at the call site).
Suggested change
ShpfyVariant.SetRange("Product Id", ProductId);
local procedure ResolveOption1Name(ProductId: BigInteger; ShopCode: Code[20]): Text[50]
var
ShpfyVariant: Record "Shpfy Variant";
...
begin
ShpfyVariant.SetRange("Shop Code", ShopCode);
ShpfyVariant.SetRange("Product Id", ProductId);
if not ShpfyVariant.FindSet() then
exit('Variant');

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

end;

local procedure CreateItemVariant(Item: Record Item; var ItemVariant: Record "Item Variant")
begin

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 1}}$

Random(999999) IDs risk cross-test data collisions

ShopifyProduct.Id and ShopifyVariant.Id are assigned with Random(999999). The small range means that concurrent or sequential test runs in a shared test database can produce duplicate IDs across different test methods, causing ResolveOption1Name to pick up variants belonging to a different test's product and producing intermittent, hard-to-diagnose failures.

Recommendation:

  • Use a higher-range random (e.g. Random(2147483647)) or derive a deterministic unique ID from the test context. If a sequence table is available, prefer that. At minimum, ensure variants are cleaned up per test or filtered with a unique shop code per test method.
Suggested change
begin
ShopifyProduct.Id := Random(2147483647);
ShopifyVariant.Id := Random(2147483647);

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@github-actions github-actions Bot removed the needs-approval Workflow runs require maintainer approval to start label Jun 10, 2026
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 From Fork Pull request is coming from a fork

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Shopify variant create uses wrong option name after initial import from Shopify

1 participant