Skip to content

Fix PromotionMigrator duplicate codes when promotions share base_code#6422

Open
NewAlexandria wants to merge 1 commit intosolidusio:mainfrom
suvie-eng:fix/promotion-migrator-duplicate-codes-join
Open

Fix PromotionMigrator duplicate codes when promotions share base_code#6422
NewAlexandria wants to merge 1 commit intosolidusio:mainfrom
suvie-eng:fix/promotion-migrator-duplicate-codes-join

Conversation

@NewAlexandria
Copy link

@NewAlexandria NewAlexandria commented Mar 2, 2026

Hi — we ran into this during our promotion migration and wanted to see if this would contribute the fix back.

We may be missing something about the intended behavior, so would appreciate a sanity check. Thanks for your time, of course.

I also added promotions/docs/PROMOTION_MIGRATOR_DUPLICATE_CODES_FIX.md with some RCA context, where we saw it, and version info.

@mrshahsuvie FYI

(an llm summary follows)


Summary

Fixes PG::UniqueViolation during promotion migration when multiple promotions have batches with the same base_code.

Problem

copy_promotion_codes joins to solidus_promotions_promotion_code_batches on base_code only. If two promotions have batches with the same base code, that join can produce multiple rows per legacy code and attempt duplicate value inserts into solidus_promotions_promotion_codes.

Solution

Constrain the batch join by:

  • promotion_id = new_promotion.id
  • created_at = spree_promotion_code_batches.created_at

This prevents cross-promotion row multiplication while preserving expected batch matching.

Testing

  • Added regression coverage in promotions/spec/lib/solidus_promotions/promotion_migrator_spec.rb for two promotions sharing the same batch base_code.
  • Verified migrated code values are inserted exactly once.
  • Ran:
    • bundle exec rspec spec/lib/solidus_promotions/promotion_migrator_spec.rb
    • bundle exec rspec (promotions engine suite)

@NewAlexandria NewAlexandria requested a review from a team as a code owner March 2, 2026 20:24
@github-actions github-actions bot added the changelog:solidus_promotions Changes to the solidus_promotions gem label Mar 2, 2026
@@ -0,0 +1,60 @@
# PromotionMigrator duplicate code fix
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this documentation should be the commit message, rather than be in the docs folder.

@codecov
Copy link

codecov bot commented Mar 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.06%. Comparing base (6477ee8) to head (6280b82).
⚠️ Report is 12 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6422      +/-   ##
==========================================
- Coverage   89.50%   89.06%   -0.44%     
==========================================
  Files         981      785     -196     
  Lines       20476    17297    -3179     
==========================================
- Hits        18327    15406    -2921     
+ Misses       2149     1891     -258     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

LEFT OUTER JOIN solidus_promotions_promotion_code_batches ON solidus_promotions_promotion_code_batches.base_code = spree_promotion_code_batches.base_code
LEFT OUTER JOIN solidus_promotions_promotion_code_batches
ON solidus_promotions_promotion_code_batches.base_code = spree_promotion_code_batches.base_code
AND solidus_promotions_promotion_code_batches.promotion_id = #{Integer(new_promotion.id)}
Copy link
Contributor

Choose a reason for hiding this comment

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

the conversion to integer in Ruby is unnecessary.

Constrain the promotion code batch join in copy_promotion_codes by promotion_id
and created_at to prevent cross-promotion row multiplication and duplicate value
inserts. Adds a regression spec and an audit doc summarizing root cause,
release verification, and related issue/PR research.
@mamhoff mamhoff force-pushed the fix/promotion-migrator-duplicate-codes-join branch from 6280b82 to 59d2748 Compare March 11, 2026 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog:solidus_promotions Changes to the solidus_promotions gem

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants