rsb-entitlements 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 989e890034f790d70eb7f72b08ec9e09c32a78a6c662d7fdfdb8c870820493b2
4
- data.tar.gz: 3792b156c3b2bedd73206fa73a42f8d5739efebdf000a54869faafa09cf96773
3
+ metadata.gz: e097db633e41702df8e93c13640f820919ba2a1cdcb8a7970f51d798ce0e2ae7
4
+ data.tar.gz: dae907fc81847c8b653d4622830ef1e92ae17e003bda00a748df47993fc92725
5
5
  SHA512:
6
- metadata.gz: fe68f954e44a3555217aa8ffa7af1c5e4adf99a3b86b5603b7eef8857a980ff025499377f7c0f1399028465249286ad1654bc76bb2ef6d91f6e20ea890659c2c
7
- data.tar.gz: c607f75ca712375e2a8369dfa291146493a0a8e8205e92c24c976c4910ebd6bdc7bc3cda21b903caad4f019bef36648c7a297a30de58f7de950f590aa1648110
6
+ metadata.gz: 9eea4bda1502c3a3ff01a3375e0db17c10b9d8eac4dc479e17cf791442e021c4946233d36aad7455a205b3164f1f676a1f7db94284dfaa1ae5123e4732d118ca
7
+ data.tar.gz: a35a9bc9ac5cd67cbdcbb471e9ae1465ee6879280d35f9a179e78eec40a31d16c1529c32e0224cb5d3d2ddf0950dcbacfbb81e1b90d70d04677c68f911a4ef9a
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateRSBEntitlementsTables < ActiveRecord::Migration[8.1]
4
+ def change
5
+ create_table :rsb_entitlements_plans do |t|
6
+ t.string :name, null: false
7
+ t.string :slug, null: false
8
+ t.string :interval, null: false
9
+ t.integer :price_cents, null: false, default: 0
10
+ t.string :currency, null: false, default: 'usd'
11
+ t.json :features, default: {}
12
+ t.json :limits, default: {}
13
+ t.json :metadata, default: {}
14
+ t.boolean :active, default: true
15
+
16
+ t.timestamps
17
+ end
18
+
19
+ add_index :rsb_entitlements_plans, :slug, unique: true
20
+ add_index :rsb_entitlements_plans, :active
21
+
22
+ create_table :rsb_entitlements_entitlements do |t|
23
+ t.references :entitleable, polymorphic: true, null: false
24
+ t.references :plan, null: false, foreign_key: { to_table: :rsb_entitlements_plans }
25
+ t.string :status, null: false, default: 'pending'
26
+ t.string :provider, null: false
27
+ t.string :provider_ref
28
+ t.datetime :activated_at
29
+ t.datetime :expires_at
30
+ t.datetime :revoked_at
31
+ t.string :revoke_reason
32
+ t.json :metadata, default: {}
33
+
34
+ t.timestamps
35
+ end
36
+
37
+ add_index :rsb_entitlements_entitlements, :status
38
+ add_index :rsb_entitlements_entitlements, :provider
39
+ add_index :rsb_entitlements_entitlements, :expires_at
40
+
41
+ create_table :rsb_entitlements_usage_counters do |t|
42
+ t.references :countable, polymorphic: true, null: false
43
+ t.string :metric, null: false
44
+ t.integer :current_value, null: false, default: 0
45
+ t.integer :limit
46
+ t.string :period_key, null: false
47
+ t.references :plan, null: false, foreign_key: { to_table: :rsb_entitlements_plans }
48
+
49
+ t.timestamps
50
+ end
51
+
52
+ add_index :rsb_entitlements_usage_counters,
53
+ %i[countable_type countable_id metric period_key plan_id],
54
+ unique: true,
55
+ name: 'idx_rsb_usage_counters_unique'
56
+ add_index :rsb_entitlements_usage_counters, :metric,
57
+ name: 'idx_rsb_usage_counters_on_metric'
58
+ add_index :rsb_entitlements_usage_counters, :period_key,
59
+ name: 'idx_rsb_usage_counters_on_period_key'
60
+
61
+ create_table :rsb_entitlements_payment_requests do |t|
62
+ t.references :requestable, polymorphic: true, null: false
63
+ t.references :plan, null: false, foreign_key: { to_table: :rsb_entitlements_plans }
64
+ t.references :entitlement, null: true, foreign_key: { to_table: :rsb_entitlements_entitlements }
65
+ t.string :provider_key, null: false
66
+ t.string :status, null: false, default: 'pending'
67
+ t.integer :amount_cents, null: false, default: 0
68
+ t.string :currency, null: false, default: 'usd'
69
+ t.string :provider_ref
70
+ t.json :provider_data, default: {}
71
+ t.text :admin_note
72
+ t.string :resolved_by
73
+ t.datetime :resolved_at
74
+ t.datetime :expires_at
75
+ t.json :metadata, default: {}
76
+
77
+ t.timestamps
78
+ end
79
+
80
+ add_index :rsb_entitlements_payment_requests,
81
+ %i[requestable_type requestable_id],
82
+ name: 'idx_payment_requests_on_requestable'
83
+ add_index :rsb_entitlements_payment_requests, :status
84
+ add_index :rsb_entitlements_payment_requests, :provider_key
85
+ add_index :rsb_entitlements_payment_requests, :expires_at,
86
+ where: "status IN ('pending', 'processing')",
87
+ name: 'idx_payment_requests_on_expires_at'
88
+ add_index :rsb_entitlements_payment_requests,
89
+ %i[requestable_type requestable_id plan_id],
90
+ unique: true,
91
+ where: "status IN ('pending', 'processing')",
92
+ name: 'idx_payment_requests_actionable_unique'
93
+ end
94
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rsb-entitlements
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksandr Marchenko
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - '='
31
31
  - !ruby/object:Gem::Version
32
- version: 0.9.1
32
+ version: 0.9.2
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - '='
38
38
  - !ruby/object:Gem::Version
39
- version: 0.9.1
39
+ version: 0.9.2
40
40
  description: Flexible plan-based feature gating, entitlements, and metered usage tracking.
41
41
  Drop-in Entitleable concern for any model. Extensible provider registry for payment
42
42
  integrations.
@@ -72,11 +72,7 @@ files:
72
72
  - app/views/rsb/entitlements/admin/usage_counters/index.html.erb
73
73
  - app/views/rsb/entitlements/admin/usage_counters/trend.html.erb
74
74
  - config/locales/admin.en.yml
75
- - db/migrate/20260208200001_create_rsb_entitlements_plans.rb
76
- - db/migrate/20260208200002_create_rsb_entitlements_entitlements.rb
77
- - db/migrate/20260208200003_create_rsb_entitlements_usage_counters.rb
78
- - db/migrate/20260208200004_create_rsb_entitlements_payment_requests.rb
79
- - db/migrate/20260213000001_rework_usage_counters_to_ledger.rb
75
+ - db/migrate/20260216200001_create_rsb_entitlements_tables.rb
80
76
  - lib/generators/rsb/entitlements/install/install_generator.rb
81
77
  - lib/rsb/entitlements.rb
82
78
  - lib/rsb/entitlements/configuration.rb
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateRSBEntitlementsPlans < ActiveRecord::Migration[8.0]
4
- def change
5
- create_table :rsb_entitlements_plans do |t|
6
- t.string :name, null: false
7
- t.string :slug, null: false
8
- t.string :interval, null: false
9
- t.integer :price_cents, null: false, default: 0
10
- t.string :currency, null: false, default: 'usd'
11
- t.json :features, default: {}
12
- t.json :limits, default: {}
13
- t.json :metadata, default: {}
14
- t.boolean :active, default: true
15
- t.timestamps
16
- end
17
-
18
- add_index :rsb_entitlements_plans, :slug, unique: true
19
- add_index :rsb_entitlements_plans, :active
20
- end
21
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateRSBEntitlementsEntitlements < ActiveRecord::Migration[8.0]
4
- def change
5
- create_table :rsb_entitlements_entitlements do |t|
6
- t.references :entitleable, polymorphic: true, null: false
7
- t.references :plan, null: false, foreign_key: { to_table: :rsb_entitlements_plans }
8
- t.string :status, null: false, default: 'pending'
9
- t.string :provider, null: false
10
- t.string :provider_ref
11
- t.datetime :activated_at
12
- t.datetime :expires_at
13
- t.datetime :revoked_at
14
- t.string :revoke_reason
15
- t.json :metadata, default: {}
16
- t.timestamps
17
- end
18
-
19
- add_index :rsb_entitlements_entitlements, :status
20
- add_index :rsb_entitlements_entitlements, :provider
21
- add_index :rsb_entitlements_entitlements, :expires_at
22
- end
23
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateRSBEntitlementsUsageCounters < ActiveRecord::Migration[8.0]
4
- def change
5
- create_table :rsb_entitlements_usage_counters do |t|
6
- t.references :countable, polymorphic: true, null: false
7
- t.string :metric, null: false
8
- t.integer :current_value, null: false, default: 0
9
- t.integer :limit
10
- t.string :period
11
- t.datetime :period_start
12
- t.datetime :resets_at
13
- t.timestamps
14
- end
15
-
16
- add_index :rsb_entitlements_usage_counters,
17
- %i[countable_type countable_id metric],
18
- unique: true,
19
- name: 'idx_rsb_usage_counters_unique'
20
- end
21
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateRSBEntitlementsPaymentRequests < ActiveRecord::Migration[8.0]
4
- def change
5
- create_table :rsb_entitlements_payment_requests do |t|
6
- t.references :requestable, polymorphic: true, null: false
7
- t.references :plan, null: false, foreign_key: { to_table: :rsb_entitlements_plans }
8
- t.references :entitlement, null: true, foreign_key: { to_table: :rsb_entitlements_entitlements }
9
- t.string :provider_key, null: false
10
- t.string :status, null: false, default: 'pending'
11
- t.integer :amount_cents, null: false, default: 0
12
- t.string :currency, null: false, default: 'usd'
13
- t.string :provider_ref
14
- t.json :provider_data, default: {}
15
- t.text :admin_note
16
- t.string :resolved_by
17
- t.datetime :resolved_at
18
- t.datetime :expires_at
19
- t.json :metadata, default: {}
20
- t.timestamps
21
- end
22
-
23
- add_index :rsb_entitlements_payment_requests,
24
- %i[requestable_type requestable_id],
25
- name: 'idx_payment_requests_on_requestable'
26
- add_index :rsb_entitlements_payment_requests, :status
27
- add_index :rsb_entitlements_payment_requests, :provider_key
28
- add_index :rsb_entitlements_payment_requests, :expires_at,
29
- where: "status IN ('pending', 'processing')",
30
- name: 'idx_payment_requests_on_expires_at'
31
- add_index :rsb_entitlements_payment_requests,
32
- %i[requestable_type requestable_id plan_id],
33
- unique: true,
34
- where: "status IN ('pending', 'processing')",
35
- name: 'idx_payment_requests_actionable_unique'
36
- end
37
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ReworkUsageCountersToLedger < ActiveRecord::Migration[8.0]
4
- def up
5
- # 1. Add new columns
6
- add_column :rsb_entitlements_usage_counters, :period_key, :string
7
- add_reference :rsb_entitlements_usage_counters, :plan,
8
- null: true,
9
- foreign_key: { to_table: :rsb_entitlements_plans }
10
-
11
- # 2. Data migration — set defaults for existing records
12
- # All existing counters become cumulative records.
13
- # Plan is set from the countable's most recent entitlement.
14
- execute <<~SQL
15
- UPDATE rsb_entitlements_usage_counters
16
- SET period_key = '__cumulative__',
17
- plan_id = (
18
- SELECT e.plan_id
19
- FROM rsb_entitlements_entitlements e
20
- WHERE e.entitleable_type = rsb_entitlements_usage_counters.countable_type
21
- AND e.entitleable_id = rsb_entitlements_usage_counters.countable_id
22
- ORDER BY e.created_at DESC
23
- LIMIT 1
24
- )
25
- SQL
26
-
27
- # 3. For any counters that still have NULL plan_id (no entitlement found),
28
- # assign the first plan as a fallback
29
- fallback_plan_id = RSB::Entitlements::Plan.first&.id
30
- if fallback_plan_id
31
- execute <<~SQL
32
- UPDATE rsb_entitlements_usage_counters
33
- SET plan_id = #{fallback_plan_id}
34
- WHERE plan_id IS NULL
35
- SQL
36
- end
37
-
38
- # 4. Data migration — convert Plan.limits from flat to nested format
39
- RSB::Entitlements::Plan.find_each do |plan|
40
- next if plan.limits.blank?
41
-
42
- # Skip if already in nested format (first value is a Hash)
43
- first_value = plan.limits.values.first
44
- next if first_value.is_a?(Hash)
45
-
46
- nested = plan.limits.transform_values do |limit_value|
47
- { 'limit' => limit_value, 'period' => nil }
48
- end
49
- plan.update_column(:limits, nested)
50
- end
51
-
52
- # 5. Make columns NOT NULL now that data is migrated
53
- change_column_null :rsb_entitlements_usage_counters, :period_key, false
54
- change_column_null :rsb_entitlements_usage_counters, :plan_id, false
55
-
56
- # 6. Drop old columns
57
- remove_column :rsb_entitlements_usage_counters, :period, :string
58
- remove_column :rsb_entitlements_usage_counters, :period_start, :datetime
59
- remove_column :rsb_entitlements_usage_counters, :resets_at, :datetime
60
-
61
- # 7. Drop old unique index and create new one
62
- remove_index :rsb_entitlements_usage_counters,
63
- name: 'idx_rsb_usage_counters_unique'
64
-
65
- add_index :rsb_entitlements_usage_counters,
66
- %i[countable_type countable_id metric period_key plan_id],
67
- unique: true,
68
- name: 'idx_rsb_usage_counters_unique'
69
-
70
- # 8. Add supporting indexes
71
- add_index :rsb_entitlements_usage_counters, :metric,
72
- name: 'idx_rsb_usage_counters_on_metric'
73
- add_index :rsb_entitlements_usage_counters, :period_key,
74
- name: 'idx_rsb_usage_counters_on_period_key'
75
- end
76
-
77
- def down
78
- raise ActiveRecord::IrreversibleMigration,
79
- 'Cannot reverse usage counter ledger migration (data migration is lossy)'
80
- end
81
- end