Create papertrail versions for newly created/updated add_on_purchases

What does this MR do and why?

The GitlabSubscriptions::Duo::BulkAssignService uses upsert_all to create addon assignments, but this bypasses ActiveRecord callbacks which are required by papertrail to create version records. This results in orphaned addon assignments without corresponding subscription_user_add_on_assignment_versions records, causing data inconsistencies in ClickHouse historical data.

Example of the insert query and the query plan:

=== SQL ===
INSERT INTO subscription_user_add_on_assignment_versions (organization_id, item_id, purchase_id, user_id, created_at, item_type, event, namespace_path, add_on_name, whodunnit, object) VALUES (1030, 290, 41, 114, '2025-09-04 10:18:20.192383', 'GitlabSubscriptions::UserAddOnAssignment', 'create', '1030/', 'code_suggestions', NULL, '{"id":290,"add_on_purchase_id":41,"user_id":114,"created_at":"2025-09-04T10:18:20.192+00:00","updated_at":"2025-09-04T10:18:20.192+00:00","organization_id":1030}'), (1030, 291, 41, 113, '2025-09-04 10:18:20.192383', 'GitlabSubscriptions::UserAddOnAssignment', 'create', '1030/', 'code_suggestions', NULL, '{"id":291,"add_on_purchase_id":41,"user_id":113,"created_at":"2025-09-04T10:18:20.192+00:00","updated_at":"2025-09-04T10:18:20.192+00:00","organization_id":1030}')
.=== QUERY PLAN ===
                                        QUERY PLAN
------------------------------------------------------------------------------------------
 Insert on subscription_user_add_on_assignment_versions  (cost=0.00..0.01 rows=0 width=0)
   ->  Result  (cost=0.00..0.01 rows=1 width=240)

References

Screenshots or screen recordings

Before After

How to set up and validate locally

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Related to #566532 (closed)

Edited by Amr Taha

Merge request reports

Loading