core_merchant 0.9.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff6bdd381d58ecdb8153a14ceff12482d22b55b70a738de1e46df9480f3ab472
4
- data.tar.gz: a87c17013865cdbe94f70daf969624f494135955568c0662e86cfe41463a6d88
3
+ metadata.gz: f2a8720cdfe9e44ee389c1f9297dca125be49ee41dd0aa36353480ebe59242f1
4
+ data.tar.gz: 8dc8ed8fd42ef4fca3ecd63b5064a0b5499da237df1fbc19bdb75301054b7646
5
5
  SHA512:
6
- metadata.gz: 044f0541c54678616eff01372b20b54e4a2bfd3f3d087ba276dc749ce06bc550f6bb047ba90bad084d1edb04f1600774cf5dd681fb56b4c91ef0c8530dbcfa38
7
- data.tar.gz: f471e4c215f2d9f36944621e9bb067f9fcde0a6f67d72ee9b6e1cc6a3a2aeb507dd93cdc110bdaf9058be19c7cb700062932609ce9f10437bb5c813c75f0ed82
6
+ metadata.gz: 76f2ff5aa75aeb8f992be5be10d1e5b7630102cf34ddf2bfcdeeafe7ac151253e27ff6dbeea2936b245af3b6965b02dce856354ae2ee7d958844e93f07cc51dd
7
+ data.tar.gz: 7175e21168584ba3b16863933e4ea5afc297fe8fb053f8502766fc8c55b1614168eb0b0c28f9ba89ca4d2e5a82d24c928b5effcbe5633dc18a38dba536d2b188
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- core_merchant (0.8.0)
4
+ core_merchant (0.10.0)
5
5
  activesupport (~> 7.0)
6
6
  rails (~> 7.0)
7
7
 
data/README.md CHANGED
@@ -11,7 +11,7 @@ CoreMerchant is a library for customer, product, and subscription management in
11
11
  - [X] Add SubscriptionPlan model
12
12
  - [X] Add Subscription model
13
13
  - [X] Implement subscription manager and callbacks
14
- - [ ] Add sidekiq jobs for subscription management
14
+ - [X] Implement SubscriptionEvent model for logging
15
15
  - [ ] Add Invoice model
16
16
  - [ ] Add billing and invoicing service
17
17
 
@@ -19,28 +19,35 @@ CoreMerchant is a library for customer, product, and subscription management in
19
19
  - [CoreMerchant](#coremerchant)
20
20
  - [To-dos until 1.0.0 release](#to-dos-until-100-release)
21
21
  - [Table of contents](#table-of-contents)
22
- - [Installation](#installation)
23
- - [Usage](#usage)
24
- - [Initialization](#initialization)
25
- - [Configuration](#configuration)
26
- - [1. Customer class](#1-customer-class)
27
- - [2. Subscription listener class](#2-subscription-listener-class)
28
- - [Subscription management](#subscription-management)
29
- - [Creating a subscription plan](#creating-a-subscription-plan)
30
- - [Creating a subscription](#creating-a-subscription)
31
- - [Cancelling a subscription](#cancelling-a-subscription)
32
- - [Handling subscription events](#handling-subscription-events)
33
- - [Models](#models)
22
+ - [Installation](#installation)
23
+ - [Usage](#usage)
24
+ - [Initialization](#initialization)
25
+ - [Configuration](#configuration)
26
+ - [1. Customer class](#1-customer-class)
27
+ - [2. Subscription listener class](#2-subscription-listener-class)
28
+ - [Subscription management](#subscription-management)
29
+ - [Creating a subscription plan](#creating-a-subscription-plan)
30
+ - [Creating a subscription](#creating-a-subscription)
31
+ - [Cancelling a subscription](#cancelling-a-subscription)
32
+ - [Handling subscription events](#handling-subscription-events)
33
+ - [Subscription History](#subscription-history)
34
+ - [Public API](#public-api)
34
35
  - [SubscriptionManager](#subscriptionmanager)
35
36
  - [SubscriptionPlan](#subscriptionplan)
36
37
  - [Subscription](#subscription)
38
+ - [SubscriptionEvent](#subscriptionevent)
39
+ - [Subclasses](#subclasses)
40
+ - [SubscriptionRenewalEvent](#subscriptionrenewalevent)
41
+ - [SubscriptionStatusChangeEvent](#subscriptionstatuschangeevent)
42
+ - [SubscriptionPlanChangeEvent](#subscriptionplanchangeevent)
43
+ - [SubscriptionCancellationEvent](#subscriptioncancellationevent)
37
44
  - [Contributing](#contributing)
38
45
 
39
46
 
40
- ## Installation
47
+ # Installation
41
48
  Add this line to your application's Gemfile:
42
49
  ```
43
- gem 'core_merchant', '~> 0.1.0'
50
+ gem 'core_merchant', '~> 0.10.0'
44
51
  ```
45
52
  and run `bundle install`.
46
53
 
@@ -49,8 +56,8 @@ Alternatively, you can install the gem manually:
49
56
  $ gem install core_merchant
50
57
  ```
51
58
 
52
- ## Usage
53
- ### Initialization
59
+ # Usage
60
+ ## Initialization
54
61
  Run the generator to create the initializer file and the migrations:
55
62
  ```
56
63
  $ rails generate core_merchant:install
@@ -66,10 +73,10 @@ You can then run the migrations:
66
73
  $ rails db:migrate
67
74
  ```
68
75
 
69
- ### Configuration
76
+ ## Configuration
70
77
  The initializer file `config/initializers/core_merchant.rb` contains the following configuration options:
71
78
 
72
- #### 1. Customer class
79
+ ### 1. Customer class
73
80
  ```ruby
74
81
  config.customer_class = 'User'
75
82
  ```
@@ -84,7 +91,7 @@ class User < ApplicationRecord
84
91
  end
85
92
  ```
86
93
 
87
- #### 2. Subscription listener class
94
+ ### 2. Subscription listener class
88
95
  ```ruby
89
96
  config.subscription_listener_class = 'MySubscriptionListener'
90
97
  ```
@@ -101,15 +108,15 @@ end
101
108
 
102
109
  More about subscription events in the [Handling subscription events](#handling-subscription-events) section.
103
110
 
104
- ### Subscription management
111
+ ## Subscription management
105
112
 
106
- #### Creating a subscription plan
113
+ ### Creating a subscription plan
107
114
  You can create a subscription plan using the `SubscriptionPlan` model:
108
115
  ```ruby
109
116
  CoreMerchant::SubscriptionPlan.create(name_key: 'basic', price_cents: 10_00, duration: '1m')
110
117
  ```
111
118
 
112
- #### Creating a subscription
119
+ ### Creating a subscription
113
120
  You can create a subscription for a customer using the `Subscription` model:
114
121
  ```ruby
115
122
  customer = User.find(1)
@@ -122,13 +129,13 @@ Note that the subscription will not be active until you start it:
122
129
  subscription.start
123
130
  ```
124
131
 
125
- #### Cancelling a subscription
132
+ ### Cancelling a subscription
126
133
  You can cancel a subscription by calling the `cancel` method. You can also specify a reason for the cancellation and whether the cancellation should take effect immediately or at the end of the current billing period:
127
134
  ```ruby
128
135
  subscription.cancel(reason: 'Customer request', at_period_end: false)
129
136
  ```
130
137
 
131
- #### Handling subscription events
138
+ ### Handling subscription events
132
139
  You can handle subscription events by implementing event handlers in the subscription listener class. For example, you can send an email to the customer when a subscription is created:
133
140
  ```ruby
134
141
  class MySubscriptionListener
@@ -173,7 +180,29 @@ Available subscription events:
173
180
  - `on_subscription_renewal_payment_processing(subscription)`
174
181
  - `on_subscription_grace_period_started(subscription, days_remaining:)`
175
182
 
176
- ## Models
183
+ ### Subscription History
184
+ CoreMerchant now keeps a detailed history of subscription events, including creations, renewals, cancellations, status changes, and plan changes. This provides an audit trail and can be useful for debugging, customer support, and analytics.
185
+
186
+ To access a subscription's history:
187
+ ```ruby
188
+ subscription = CoreMerchant::Subscription.find(42)
189
+
190
+ # Get all events
191
+ subscription.subscription_events
192
+
193
+ # Get specific event types
194
+ latest_renewal = subscription.renewal_events.last
195
+ puts "Last renewed at: #{latest_renewal.created_at}"
196
+ puts "Renewal price: #{latest_renewal.price_cents} cents, renewed until: #{latest_renewal.renewed_until}"
197
+
198
+ latest_status_change = subscription.status_change_events.last
199
+ puts "Status changed from #{latest_status_change.from} to #{latest_status_change.to}"
200
+
201
+ latest_plan_change = subscription.plan_change_events.last
202
+ puts "Plan changed from #{latest_plan_change.from_plan.name} to #{latest_plan_change.to_plan.name}"
203
+ ```
204
+
205
+ ## Public API
177
206
  ### SubscriptionManager
178
207
  Access from `CoreMerchant.subscription_manager`. The `SubscriptionManager` class is responsible for managing subscriptions. It is responsible for notifying listeners when subscription events occur and checking for and handling renewals.
179
208
 
@@ -271,6 +300,53 @@ subscription.start
271
300
  subscription.cancel(reason: "Too expensive", at_period_end: true)
272
301
  ```
273
302
 
303
+ ### SubscriptionEvent
304
+ The `SubscriptionEvent` model represents a historical log of events related to a subscription. It provides an audit trail of all significant actions and state changes for a subscription.
305
+
306
+ This class has subclasses for specific event types, such as `SubscriptionRenewalEvent`, `SubscriptionStatusChangeEvent`, and `SubscriptionPlanChangeEvent`. Each subclass has additional fields specific to the event type.
307
+
308
+ **Attributes**:
309
+ - `subscription`: Association to the related Subscription
310
+ - `event_type`: Type of the event (e.g., 'created', 'renewed', 'canceled', 'status_changed', 'plan_changed')
311
+ - `metadata`: JSON field for storing additional event-specific data
312
+
313
+ **Usage**:
314
+ ```ruby
315
+ # Automatically logged when a subscription is created
316
+ subscription = CoreMerchant::Subscription.create(customer: user, subscription_plan: plan)
317
+
318
+ # Logging a custom event
319
+ subscription.log_event('custom_event', key: 'value')
320
+
321
+ # Retrieve the last renewal event
322
+ latest_renewal = subscription.renewal_events.last
323
+ puts "Last renewed at: #{latest_renewal.created_at}"
324
+ puts "Renewal price: #{latest_renewal.price_cents} cents, renewed until: #{latest_renewal.renewed_until}"
325
+
326
+ # Retrieve the last event of any type
327
+ latest_event = subscription.subscription_events.last
328
+ puts "Last event type: #{latest_event.event_type}, metadata: #{latest_event.metadata}"
329
+ ```
330
+
331
+ #### Subclasses
332
+ ##### SubscriptionRenewalEvent
333
+ - `price_cents`: The price of the renewal in cents
334
+ - `renewed_until`: The end date of the renewal
335
+ - `renewed_at`: The date and time of the renewal
336
+
337
+ ##### SubscriptionStatusChangeEvent
338
+ - `from`: The previous status of the subscription
339
+ - `to`: The new status of the subscription
340
+
341
+ ##### SubscriptionPlanChangeEvent
342
+ - `from_plan`: The previous plan of the subscription
343
+ - `to_plan`: The new plan of the subscription
344
+
345
+ ##### SubscriptionCancellationEvent
346
+ - `reason`: The reason for the cancellation
347
+ - `at_period_end`: Whether the cancellation is scheduled for the end of the current period
348
+ - `canceled_at`: The date and time of the cancellation
349
+
274
350
  > [!NOTE]
275
351
  > Other models and features are being developed and will be added in future releases.
276
352
 
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CoreMerchant
4
+ module Concerns
5
+ # This concern adds a SubscriptionEvent association including creation and retrieval
6
+ module SubscriptionEventAssociation
7
+ extend ActiveSupport::Concern
8
+
9
+ EVENT_TYPES = %i[renewal status_change plan_change cancellation].freeze
10
+
11
+ included do
12
+ has_many :events, class_name: "SubscriptionEvent", dependent: :destroy
13
+ after_update :create_status_change_event, if: :saved_change_to_status?
14
+
15
+ EVENT_TYPES.each do |event_type|
16
+ scope_name = "#{event_type}_events".to_sym
17
+ class_name = "Subscription#{event_type.to_s.camelize}Event"
18
+
19
+ has_many scope_name, -> { where(event_type: event_type) }, class_name: class_name
20
+
21
+ define_method "create_#{event_type}_event" do |**metadata|
22
+ events.create!(event_type: event_type, metadata: metadata)
23
+ end
24
+ end
25
+
26
+ def create_status_change_event
27
+ status_change_events.create!(from: saved_changes["status"].first, to: status)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  require "core_merchant/concerns/subscription_state_machine"
4
4
  require "core_merchant/concerns/subscription_notifications"
5
+ require "core_merchant/concerns/subscription_event_association"
6
+ require "core_merchant/subscription_event"
5
7
 
6
8
  module CoreMerchant
7
9
  # Represents a subscription in CoreMerchant.
@@ -52,6 +54,7 @@ module CoreMerchant
52
54
  class Subscription < ActiveRecord::Base # rubocop:disable Metrics/ClassLength
53
55
  include CoreMerchant::Concerns::SubscriptionStateMachine
54
56
  include CoreMerchant::Concerns::SubscriptionNotifications
57
+ include CoreMerchant::Concerns::SubscriptionEventAssociation
55
58
 
56
59
  self.table_name = "core_merchant_subscriptions"
57
60
 
@@ -120,6 +123,7 @@ module CoreMerchant
120
123
  end
121
124
 
122
125
  notify_subscription_manager(:canceled, reason: reason, immediate: !at_period_end)
126
+ cancellation_events.create!(reason: reason, at_period_end: at_period_end)
123
127
  end
124
128
 
125
129
  # Starts a new period for the subscription.
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CoreMerchant
4
+ # The `SubscriptionEvent` model represents a historical log of events related to a subscription.
5
+ # It provides an audit trail of all significant actions and state changes for a subscription.
6
+
7
+ # This class has subclasses for specific event types, such as
8
+ # `SubscriptionRenewalEvent`, `SubscriptionStatusChangeEvent`, and `SubscriptionPlanChangeEvent`.
9
+ # Each subclass has additional fields specific to the event type.
10
+
11
+ # **Attributes**:
12
+ # - `subscription`: Association to the related Subscription
13
+ # - `event_type`: Type of the event (e.g., 'created', 'renewed', 'canceled', 'status_changed', 'plan_changed')
14
+ # - `metadata`: JSON field for storing additional event-specific data
15
+
16
+ # **Usage**:
17
+ # ```ruby
18
+ # # Automatically logged when a subscription is created
19
+ # subscription = CoreMerchant::Subscription.create(customer: user, subscription_plan: plan)
20
+
21
+ # # Logging a custom event
22
+ # subscription.log_event('custom_event', key: 'value')
23
+
24
+ # # Retrieve the last renewal event
25
+ # latest_renewal = subscription.renewal_events.last
26
+ # puts "Last renewed at: #{latest_renewal.created_at}"
27
+ # puts "Renewal price: #{latest_renewal.price_cents} cents, renewed until: #{latest_renewal.renewed_until}"
28
+
29
+ # # Retrieve the last event of any type
30
+ # latest_event = subscription.subscription_events.last
31
+ # puts "Last event type: #{latest_event.event_type}, metadata: #{latest_event.metadata}"
32
+ # ```
33
+ class SubscriptionEvent < ActiveRecord::Base
34
+ self.table_name = "core_merchant_subscription_events"
35
+
36
+ belongs_to :subscription, class_name: "CoreMerchant::Subscription"
37
+
38
+ validates :event_type, presence: true
39
+
40
+ def metadata
41
+ value = self[:metadata]
42
+ value.is_a?(Hash) ? value : JSON.parse(value || "{}")
43
+ end
44
+
45
+ def metadata=(value)
46
+ self[:metadata] = value.is_a?(Hash) ? value.to_json : value
47
+ end
48
+ end
49
+
50
+ # Represents a renewal event for a subscription.
51
+ class SubscriptionRenewalEvent < SubscriptionEvent
52
+ def price_cents
53
+ metadata["price_cents"]
54
+ end
55
+
56
+ def price_cents=(value)
57
+ self.metadata = metadata.merge(price_cents: value)
58
+ end
59
+
60
+ def renewed_from
61
+ metadata["renewed_from"].to_date
62
+ end
63
+
64
+ def renewed_from=(value)
65
+ self.metadata = metadata.merge(renewed_from: value)
66
+ end
67
+
68
+ def renewed_until
69
+ metadata["renewed_until"].to_date
70
+ end
71
+
72
+ def renewed_until=(value)
73
+ self.metadata = metadata.merge(renewed_until: value)
74
+ end
75
+ end
76
+
77
+ # Represents a status change event for a subscription.
78
+ class SubscriptionStatusChangeEvent < SubscriptionEvent
79
+ def from
80
+ metadata["from_status"]
81
+ end
82
+
83
+ def from=(value)
84
+ self.metadata = metadata.merge(from_status: value)
85
+ end
86
+
87
+ def to
88
+ metadata["to_status"]
89
+ end
90
+
91
+ def to=(value)
92
+ self.metadata = metadata.merge(to_status: value)
93
+ end
94
+ end
95
+
96
+ # Represents a plan change event for a subscription.
97
+ class SubscriptionPlanChangeEvent < SubscriptionEvent
98
+ def from_plan
99
+ id = metadata["from_plan_id"]
100
+ CoreMerchant::SubscriptionPlan.find(id) if id
101
+ end
102
+
103
+ def from_plan=(value)
104
+ self.metadata = metadata.merge(from_plan_id: value.id)
105
+ end
106
+
107
+ def to_plan
108
+ id = metadata["to_plan_id"]
109
+ CoreMerchant::SubscriptionPlan.find(id) if id
110
+ end
111
+
112
+ def to_plan=(value)
113
+ self.metadata = metadata.merge(to_plan_id: value.id)
114
+ end
115
+ end
116
+
117
+ # Represents a cancellation event for a subscription.
118
+ class SubscriptionCancellationEvent < SubscriptionEvent
119
+ def canceled_at
120
+ created_at
121
+ end
122
+
123
+ def at_period_end?
124
+ metadata["at_period_end"]
125
+ end
126
+
127
+ def at_period_end=(value)
128
+ self.metadata = metadata.merge(at_period_end: value)
129
+ end
130
+
131
+ def reason
132
+ metadata["reason"]
133
+ end
134
+
135
+ def reason=(value)
136
+ self.metadata = metadata.merge(reason: value)
137
+ end
138
+ end
139
+ end
@@ -104,6 +104,11 @@ module CoreMerchant
104
104
  return unless subscription.transition_to_active
105
105
 
106
106
  subscription.start_new_period
107
+ subscription.renewal_events.create!(
108
+ price_cents: subscription.subscription_plan.price_cents,
109
+ renewed_from: subscription.current_period_start, renewed_until: subscription.current_period_end
110
+ )
111
+
107
112
  notify(subscription, :renewed)
108
113
  end
109
114
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CoreMerchant
4
- VERSION = "0.9.0"
4
+ VERSION = "0.10.1"
5
5
  end
@@ -28,6 +28,9 @@ module CoreMerchant
28
28
 
29
29
  migration_template "migrate/create_core_merchant_subscriptions.erb",
30
30
  "db/migrate/create_core_merchant_subscriptions.rb"
31
+
32
+ migration_template "migrate/create_core_merchant_subscription_events.erb",
33
+ "db/migrate/create_core_merchant_subscription_events.rb"
31
34
  end
32
35
 
33
36
  def show_post_install
@@ -36,7 +39,7 @@ module CoreMerchant
36
39
  Next steps:
37
40
  1. Set the customer class in the initializer file (config/initializers/core_merchant.rb) to the class you want to use for customers.
38
41
  2. Create a subscription listener class (should include CoreMerchant::SubscriptionListener) in your app and set this class in the initializer file (config/initializers/core_merchant.rb) to the class you want to use for subscription listeners.
39
- 3. Run `rails db:migrate` to create the subscription and subscription plan tables.
42
+ 3. Run `rails db:migrate` to create the subscription, subscription plan, and subscription event tables.
40
43
  MESSAGE
41
44
  say next_steps, :yellow
42
45
  end
@@ -47,7 +50,7 @@ module CoreMerchant
47
50
 
48
51
  def self.description
49
52
  <<~DESC
50
- Installs CoreMerchant into your application. This generator will create an initializer file, migration files for the subscription and subscription plan tables, and a locale file."
53
+ Installs CoreMerchant into your application. This generator will create an initializer file, migration files for the subscription, subscription plan, and subscription event tables, and a locale file.
51
54
  DESC
52
55
  end
53
56
  end
@@ -7,7 +7,7 @@ CoreMerchant.configure do |config|
7
7
  # include CoreMerchant::CustomerBehavior
8
8
  # ...
9
9
  # end
10
- config.customer_class = "User"
10
+ # config.customer_class = "User"
11
11
 
12
12
  # Set the class that will receive subscription notifications/
13
13
  # This class must include the CoreMerchant::SubscriptionListener module.
@@ -22,5 +22,5 @@ CoreMerchant.configure do |config|
22
22
  #
23
23
  # To test notifications to this class, you can override `on_test_event_received` method
24
24
  # and call `CoreMerchant.subscription_manager.notify_test_event`.
25
- config.subscription_listener_class = "SubscriptionListener"
25
+ # config.subscription_listener_class = "SubscriptionListener"
26
26
  end
@@ -0,0 +1,14 @@
1
+ # Created by: rails generate core_merchant:install
2
+ class CreateCoreMerchantSubscriptionEvents < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
3
+ def change
4
+ create_table :core_merchant_subscription_events do |t|
5
+ t.references :subscription, null: false, foreign_key: { to_table: :core_merchant_subscriptions }
6
+ t.string :event_type, null: false
7
+ t.jsonb :metadata, default: {}, null: false
8
+
9
+ t.timestamps
10
+
11
+ t.index :event_type
12
+ end
13
+ end
14
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: core_merchant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seyithan Teymur
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-24 00:00:00.000000000 Z
11
+ date: 2024-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -144,11 +144,13 @@ files:
144
144
  - Rakefile
145
145
  - core_merchant.gemspec
146
146
  - lib/core_merchant.rb
147
+ - lib/core_merchant/concerns/subscription_event_association.rb
147
148
  - lib/core_merchant/concerns/subscription_manager_notifications.rb
148
149
  - lib/core_merchant/concerns/subscription_notifications.rb
149
150
  - lib/core_merchant/concerns/subscription_state_machine.rb
150
151
  - lib/core_merchant/customer_behavior.rb
151
152
  - lib/core_merchant/subscription.rb
153
+ - lib/core_merchant/subscription_event.rb
152
154
  - lib/core_merchant/subscription_listener.rb
153
155
  - lib/core_merchant/subscription_manager.rb
154
156
  - lib/core_merchant/subscription_plan.rb
@@ -156,6 +158,7 @@ files:
156
158
  - lib/generators/core_merchant/install_generator.rb
157
159
  - lib/generators/core_merchant/templates/core_merchant.en.yml
158
160
  - lib/generators/core_merchant/templates/core_merchant.rb
161
+ - lib/generators/core_merchant/templates/migrate/create_core_merchant_subscription_events.erb
159
162
  - lib/generators/core_merchant/templates/migrate/create_core_merchant_subscription_plans.erb
160
163
  - lib/generators/core_merchant/templates/migrate/create_core_merchant_subscriptions.erb
161
164
  - sig/core_merchant.rbs