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 +4 -4
- data/db/migrate/20260216200001_create_rsb_entitlements_tables.rb +94 -0
- metadata +4 -8
- data/db/migrate/20260208200001_create_rsb_entitlements_plans.rb +0 -21
- data/db/migrate/20260208200002_create_rsb_entitlements_entitlements.rb +0 -23
- data/db/migrate/20260208200003_create_rsb_entitlements_usage_counters.rb +0 -21
- data/db/migrate/20260208200004_create_rsb_entitlements_payment_requests.rb +0 -37
- data/db/migrate/20260213000001_rework_usage_counters_to_ledger.rb +0 -81
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e097db633e41702df8e93c13640f820919ba2a1cdcb8a7970f51d798ce0e2ae7
|
|
4
|
+
data.tar.gz: dae907fc81847c8b653d4622830ef1e92ae17e003bda00a748df47993fc92725
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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.
|
|
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.
|
|
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.
|
|
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/
|
|
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
|