'use strict'; // Tier Plans v2: item-specific entitlement means two DIFFERENT plans at the // SAME tier slug (e.g. two separate Premium bundles) must be able to stay // concurrently active for one user, each governing its own distinct // user_tier_grants snapshot — buying a second Premium bundle must not just // extend the first one's expiry (see captureOrder in // controllers/client/tiers.controller.js). // // The old partial unique index (20270101000075) enforced "one active row per // (user_id, tier)", which blocks that. Replace it with "one active row per // (user_id, plan_id)" — still prevents accidentally double-purchasing/ // double-granting the exact same plan concurrently, but allows multiple // plans at the same tier to coexist. NULL plan_id rows (admin-granted // tiers with no backing plan) are never considered equal to one another by // a unique index, so they're unaffected. // // NOT auto-run — do not execute against the shared dev/prod database without // explicit confirmation. module.exports = { async up(queryInterface) { await queryInterface.removeIndex('user_tiers', 'user_tiers_one_active_per_user_tier'); await queryInterface.addIndex('user_tiers', ['user_id', 'plan_id'], { unique: true, where: { status: 'active' }, name: 'user_tiers_one_active_per_user_plan', }); }, async down(queryInterface) { await queryInterface.removeIndex('user_tiers', 'user_tiers_one_active_per_user_plan'); await queryInterface.addIndex('user_tiers', ['user_id', 'tier'], { unique: true, where: { status: 'active' }, name: 'user_tiers_one_active_per_user_tier', }); }, };