[Shopify] Fix #7724: Resolve Option 1 Name from existing Shopify Variant records#8577
[Shopify] Fix #7724: Resolve Option 1 Name from existing Shopify Variant records#8577tVisionDeb wants to merge 1 commit into
Conversation
…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.
|
Hi @onbuyuka - thank you for the thorough review on the previous PR (#8048). I have addressed all your feedback: Changes made:
Local test results (BC v29 container):
Ready for re-review. |
| end; | ||
| if ShopifyVariant."Option 1 Name" = '' then | ||
| ShopifyVariant."Option 1 Name" := 'Variant'; | ||
| if ShopifyVariant."Option 1 Name" = 'Variant' then |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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).
| 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 |
There was a problem hiding this comment.
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.
| begin | |
| ShopifyProduct.Id := Random(2147483647); | |
| ShopifyVariant.Id := Random(2147483647); |
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why
Summary
Fixes #7724 - regression introduced in PR #7660 where
Option 1 Namewas being reset to'Variant'for Shopify-origin products whose variants already have a differentOption 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 setOption 1 Valuewhen the resolved name was anything other than'Variant'. The guard condition was missing theJustResolvedOption1Nameflag.Fix
Added a
JustResolvedOption1Nameboolean so thatOption 1 Valueis 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:
UnitTestOption1NameInheritedFromShopifyOriginProduct- Shopify-origin product with existing variants keeps their Option 1 Name and sets Option 1 Value correctlyUnitTestOption1NameDefaultsToVariantForBCOriginProduct- BC-origin product (no existing Shopify variants) gets 'Variant' as Option 1 NameUnitTestOption1NameDefaultsToVariantWhenNoExistingVariants- No existing variants defaults to 'Variant'UnitTestOption1NameDefaultsToVariantWhenAmbiguous- Ambiguous case (multiple different Option 1 Names) defaults to 'Variant'UnitTestOption1NameAndValuePreservedOnUpdatePath- Update path: pre-existing Option 1 Name is preserved and Option 1 Value is set correctlyAll 5 new tests pass locally on BC v29. Existing codeunit 139601 (Product Export) also passes - no regression introduced.