accountability 0.1.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +86 -9
- data/app/assets/stylesheets/accountability/application.scss +0 -0
- data/app/controllers/accountability/accounts_controller.rb +2 -4
- data/app/controllers/accountability/billing_configurations_controller.rb +80 -0
- data/app/controllers/accountability/order_groups_controller.rb +2 -4
- data/app/controllers/accountability/payments_controller.rb +25 -0
- data/app/controllers/accountability/products_controller.rb +7 -5
- data/app/controllers/accountability/statements_controller.rb +19 -0
- data/app/controllers/accountability_controller.rb +47 -0
- data/app/helpers/accountability/{application_helper.rb → accountability_helper.rb} +1 -1
- data/app/helpers/accountability/billing_configurations_helper.rb +47 -0
- data/app/helpers/accountability/products_helper.rb +21 -0
- data/app/models/accountability/account.rb +31 -1
- data/app/models/accountability/application_record.rb +24 -0
- data/app/models/accountability/billing_configuration.rb +41 -0
- data/app/models/accountability/coupon.rb +2 -0
- data/app/models/accountability/credit.rb +53 -29
- data/app/models/accountability/debit.rb +10 -0
- data/app/models/accountability/inventory.rb +61 -0
- data/app/models/accountability/offerable.rb +28 -1
- data/app/models/accountability/offerable/scope.rb +48 -0
- data/app/models/accountability/order_item.rb +3 -7
- data/app/models/accountability/payment.rb +22 -3
- data/app/models/accountability/product.rb +45 -5
- data/app/models/accountability/statement.rb +46 -0
- data/app/models/accountability/{account/transactions.rb → transactions.rb} +14 -2
- data/app/models/concerns/accountability/active_merchant_interface.rb +15 -0
- data/app/models/concerns/accountability/active_merchant_interface/stripe_interface.rb +134 -0
- data/app/pdfs/statement_pdf.rb +91 -0
- data/app/views/accountability/accounts/show.html.haml +21 -9
- data/app/views/accountability/products/index.html.haml +17 -34
- data/app/views/accountability/products/new.html.haml +73 -0
- data/app/views/accountability/shared/_session_info.html.haml +24 -0
- data/config/locales/en.yml +19 -0
- data/db/migrate/20190814000455_create_accountability_tables.rb +43 -1
- data/lib/accountability.rb +2 -1
- data/lib/accountability/configuration.rb +22 -2
- data/lib/accountability/engine.rb +6 -1
- data/lib/accountability/extensions/acts_as_billable.rb +11 -0
- data/lib/accountability/rails/routes.rb +72 -0
- data/lib/accountability/types.rb +9 -0
- data/lib/accountability/types/billing_configuration_types.rb +57 -0
- data/lib/accountability/version.rb +1 -1
- data/lib/generators/accountability/install_generator.rb +47 -0
- data/lib/generators/accountability/templates/migration.rb.tt +155 -0
- data/lib/generators/accountability/templates/price_overrides_migration.rb.tt +13 -0
- metadata +73 -12
- data/app/assets/stylesheets/accountability/application.css +0 -15
- data/app/controllers/accountability/application_controller.rb +0 -45
- data/app/views/accountability/products/new.html.erb +0 -40
- data/lib/accountability/cartographer.rb +0 -28
@@ -0,0 +1,73 @@
|
|
1
|
+
.container
|
2
|
+
= link_to 'Back', accountability_products_path, class: 'btn btn-outline-primary float-right'
|
3
|
+
|
4
|
+
%h1.mb-5 New Product
|
5
|
+
|
6
|
+
- @product.errors.full_messages.each do |message|
|
7
|
+
.alert.alert-danger
|
8
|
+
= message
|
9
|
+
|
10
|
+
= form_with model: [:accountability, @product], local: true do |f|
|
11
|
+
.card.my-3
|
12
|
+
.card-body
|
13
|
+
-# WHEN I GET BACK - Add scope fields and stuff - they only show when @stage is set to 'final' from :create
|
14
|
+
-# .. also we should probably run validations on the fields we show .. or at least the category field
|
15
|
+
|
16
|
+
-# TODO: Add dev only instructions
|
17
|
+
|
18
|
+
%h3.mb-4 Product Info
|
19
|
+
|
20
|
+
.form-row
|
21
|
+
.form-group.col-md-4
|
22
|
+
= f.label :offerable_category
|
23
|
+
= f.select :offerable_category, source_class_options, { }, { disabled: disable_category_field?, class: 'form-control' }
|
24
|
+
.form-group.col-md-8
|
25
|
+
= f.label :name
|
26
|
+
= f.text_field :name, class: 'form-control'
|
27
|
+
.form-group.optional-fields.col-md-2
|
28
|
+
= f.label :sku
|
29
|
+
= f.text_field :sku, class: 'form-control'
|
30
|
+
.form-group.col-md-3
|
31
|
+
= f.label :price
|
32
|
+
= f.number_field :price, step: 2, class: 'form-control'
|
33
|
+
.form-group.col-md-4
|
34
|
+
= f.label :schedule
|
35
|
+
= f.select :schedule, schedule_options, {}, {class: 'form-control' }
|
36
|
+
.form-group.col-md-3
|
37
|
+
= f.label :quantity
|
38
|
+
= f.text_field :quantity, class: 'form-control'
|
39
|
+
.form-group.col-md-12
|
40
|
+
= f.label :description
|
41
|
+
= f.text_area :description, class: 'form-control'
|
42
|
+
|
43
|
+
- if @stage == 'final'
|
44
|
+
|
45
|
+
%hr
|
46
|
+
.card-body
|
47
|
+
%h3.mb-4 Details
|
48
|
+
.form-row
|
49
|
+
- @product.scopes.each do |scope|
|
50
|
+
.form-group.col-md-12
|
51
|
+
= f.label :offerable_category, scope.title.titleize
|
52
|
+
= f.select :offerable_category, scope_options(scope), { }, { class: 'form-control' }
|
53
|
+
|
54
|
+
%hr
|
55
|
+
.card-body
|
56
|
+
%h3.mb-4 Availability Options
|
57
|
+
|
58
|
+
.form-row
|
59
|
+
.form-group.optional-fields.col-md-12
|
60
|
+
= f.label :activation_date
|
61
|
+
= f.datetime_field :activation_date, class: 'form-control'
|
62
|
+
%em.small Product or service becomes available for purchase and use
|
63
|
+
.form-group.optional-fields.col-md-12
|
64
|
+
= f.label :expiration_date
|
65
|
+
= f.datetime_field :expiration_date, class: 'form-control'
|
66
|
+
%em.small Product or service is no longer available for purchase
|
67
|
+
.form-group.optional-fields.col-md-12
|
68
|
+
= f.label :termination_date
|
69
|
+
= f.datetime_field :termination_date, class: 'form-control'
|
70
|
+
%em.small Product or service is no longer available for use
|
71
|
+
|
72
|
+
= link_to 'Reset', new_accountability_product_path, class: 'btn btn-outline-secondary float-right'
|
73
|
+
= f.button 'Submit', type: :submit, name: :stage, value: @stage, class: 'btn btn-success'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
.card.mb-5
|
2
|
+
.card-header
|
3
|
+
Session Info
|
4
|
+
.row.no-gutters
|
5
|
+
.col-md-6
|
6
|
+
.card-body.pb-1
|
7
|
+
%p
|
8
|
+
%strong.text-primary Billable Record:
|
9
|
+
= current_account&.billable_record_name
|
10
|
+
|
11
|
+
%p
|
12
|
+
%strong.text-primary Admin Session:
|
13
|
+
= admin_session? ? 'Yes' : 'No'
|
14
|
+
|
15
|
+
.col-md-6
|
16
|
+
.card-body.pb-1
|
17
|
+
|
18
|
+
%p
|
19
|
+
%strong.text-primary OrderGroup ID:
|
20
|
+
= current_order_group&.id
|
21
|
+
|
22
|
+
%p
|
23
|
+
%strong.text-primary Account ID:
|
24
|
+
= current_account&.id
|
@@ -0,0 +1,19 @@
|
|
1
|
+
en:
|
2
|
+
activerecord:
|
3
|
+
attributes:
|
4
|
+
'accountability/product':
|
5
|
+
offerable_category: "Category"
|
6
|
+
schedule: "Billing Schedule"
|
7
|
+
quantity: "Bundle Size"
|
8
|
+
sku: "SKU"
|
9
|
+
accountability:
|
10
|
+
gateway:
|
11
|
+
errors:
|
12
|
+
unknown_gateway_error: "An unknown gateway error has occurred"
|
13
|
+
helpers:
|
14
|
+
label:
|
15
|
+
billing_configuration:
|
16
|
+
configuration_name: "Payment Method Name"
|
17
|
+
contact_email: "Billing Email"
|
18
|
+
contact_first_name: "First Name"
|
19
|
+
contact_last_name: "Last Name"
|
@@ -1,16 +1,24 @@
|
|
1
1
|
# rubocop:disable Metrics/AbcSize
|
2
|
+
# rubocop:disable Metrics/LineLength
|
2
3
|
# rubocop:disable Metrics/MethodLength
|
3
4
|
|
4
5
|
class CreateAccountabilityTables < ActiveRecord::Migration[6.0]
|
5
6
|
def change
|
6
7
|
create_table :accountability_accounts do |t|
|
7
8
|
t.belongs_to :billable, null: true, polymorphic: true
|
8
|
-
|
9
|
+
t.integer :statement_schedule, default: 0, null: false # end_of_month bi_weekly
|
9
10
|
t.datetime :last_balanced_at, default: nil, null: true
|
10
11
|
|
11
12
|
t.timestamps
|
12
13
|
end
|
13
14
|
|
15
|
+
create_table :accountability_statements do |t|
|
16
|
+
t.belongs_to :account, null: false, index: { name: :index_account_on_statement }
|
17
|
+
t.datetime :end_date, default: nil, null: false
|
18
|
+
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
|
14
22
|
create_table :accountability_debits do |t|
|
15
23
|
t.belongs_to :account, null: false, index: { name: :index_account_on_debit }
|
16
24
|
t.belongs_to :payment, null: true, index: { name: :index_payment_on_debit }
|
@@ -22,13 +30,17 @@ class CreateAccountabilityTables < ActiveRecord::Migration[6.0]
|
|
22
30
|
create_table :accountability_credits do |t|
|
23
31
|
t.belongs_to :account, null: false, index: { name: :index_account_on_credit }
|
24
32
|
t.belongs_to :order_item, null: false, index: { name: :index_order_item_on_credit }
|
33
|
+
t.belongs_to :statement, null: false, index: { name: :index_statement_on_credit }
|
25
34
|
t.decimal :amount, default: 0.00, precision: 8, scale: 2, null: false
|
35
|
+
t.decimal :taxes, default: 0.00, precision: 8, scale: 2, null: false
|
26
36
|
|
27
37
|
t.timestamps
|
28
38
|
end
|
29
39
|
|
30
40
|
create_table :accountability_payments do |t|
|
31
41
|
t.belongs_to :account, null: false, index: { name: :index_account_on_payment }
|
42
|
+
t.belongs_to :billing_configuration, null: false, index: { name: :index_billing_configuration_on_payment }
|
43
|
+
|
32
44
|
t.decimal :amount, default: 0.00, precision: 8, scale: 2, null: false
|
33
45
|
t.integer :status, default: 0, null: false # Pending, Processing, Complete, Failed
|
34
46
|
|
@@ -72,6 +84,7 @@ class CreateAccountabilityTables < ActiveRecord::Migration[6.0]
|
|
72
84
|
|
73
85
|
create_table :accountability_products do |t|
|
74
86
|
t.boolean :public, default: true, null: false
|
87
|
+
t.boolean :tax_exempt, default: false, null: false
|
75
88
|
t.decimal :price, default: 0.00, precision: 8, scale: 2, null: false
|
76
89
|
t.integer :quantity, default: 1, null: false
|
77
90
|
t.string :name, default: nil, null: false
|
@@ -105,13 +118,42 @@ class CreateAccountabilityTables < ActiveRecord::Migration[6.0]
|
|
105
118
|
t.timestamps
|
106
119
|
end
|
107
120
|
|
121
|
+
# rubocop:disable Rails/CreateTableWithTimestamps
|
108
122
|
create_table :accountability_coupons_products, id: false do |t|
|
109
123
|
t.belongs_to :product, index: { name: :index_product_on_product_coupon }
|
110
124
|
t.belongs_to :coupon, index: { name: :index_coupon_on_product_coupon }
|
111
125
|
end
|
126
|
+
# rubocop:enable Rails/CreateTableWithTimestamps
|
112
127
|
|
128
|
+
# rubocop:disable Rails/CreateTableWithTimestamps
|
113
129
|
create_table :accountability_identities do |t|
|
114
130
|
t.belongs_to :identifiable, polymorphic: true, index: { name: :index_identifiable_on_identity }
|
115
131
|
end
|
132
|
+
# rubocop:enable Rails/CreateTableWithTimestamps
|
133
|
+
|
134
|
+
create_table :accountability_billing_configurations do |t|
|
135
|
+
t.belongs_to :account, null: false, index: { name: :index_account_on_billing_configuration }
|
136
|
+
t.boolean :primary, default: false, null: false
|
137
|
+
t.text :billing_address, default: nil, null: true # JSON serialized value object
|
138
|
+
t.text :active_merchant_data, default: nil, null: true # JSON serialized data for ActiveMerchant
|
139
|
+
t.integer :provider, default: 0, null: false # [unselected, stripe]
|
140
|
+
t.string :token, default: nil, null: true # Used to retrieve & charge the payment method from the provider
|
141
|
+
t.string :configuration_name, default: nil, null: true # A name for the payment method
|
142
|
+
t.string :contact_email, default: nil, null: true
|
143
|
+
t.string :contact_first_name, default: nil, null: true
|
144
|
+
t.string :contact_last_name, default: nil, null: true
|
145
|
+
|
146
|
+
t.timestamps
|
147
|
+
end
|
148
|
+
|
149
|
+
create_table :accountability_price_overrides do |t|
|
150
|
+
t.belongs_to :product, index: { name: :index_product_on_price_override }
|
151
|
+
t.belongs_to :offerable_source, null: false, polymorphic: true, index: { name: :index_offerable_source_on_price_override }
|
152
|
+
|
153
|
+
t.decimal :price, default: 0.00, precision: 8, scale: 2, null: false # The inventory item's new price
|
154
|
+
t.text :description, default: nil, null: true, limit: 10_000 # Optional field for describing adjustment rationale
|
155
|
+
|
156
|
+
t.timestamps
|
157
|
+
end
|
116
158
|
end
|
117
159
|
end
|
data/lib/accountability.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require_dependency 'accountability/engine'
|
2
2
|
require_dependency 'accountability/configuration'
|
3
|
-
require_dependency 'accountability/
|
3
|
+
require_dependency 'accountability/rails/routes'
|
4
4
|
require_dependency 'accountability/extensions'
|
5
|
+
require_dependency 'accountability/types'
|
5
6
|
|
6
7
|
module Accountability
|
7
8
|
def self.configure(_tenant = :default)
|
@@ -1,8 +1,12 @@
|
|
1
1
|
module Accountability
|
2
2
|
class Configuration
|
3
3
|
class << self
|
4
|
-
attr_accessor :
|
5
|
-
attr_writer :admin_checker
|
4
|
+
attr_accessor :logo_path, :payment_gateway, :dev_tools_enabled
|
5
|
+
attr_writer :tax_rate, :admin_checker, :billable_identifier, :billable_name_column
|
6
|
+
|
7
|
+
def tax_rate
|
8
|
+
@tax_rate || 0.0
|
9
|
+
end
|
6
10
|
|
7
11
|
def admin_checker
|
8
12
|
if @admin_checker.is_a? Proc
|
@@ -11,6 +15,22 @@ module Accountability
|
|
11
15
|
-> { true }
|
12
16
|
end
|
13
17
|
end
|
18
|
+
|
19
|
+
def billable_identifier
|
20
|
+
if @billable_identifier.is_a? Proc
|
21
|
+
@billable_identifier
|
22
|
+
else
|
23
|
+
-> { @current_user }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def billable_name_column
|
28
|
+
@billable_name_column || :id
|
29
|
+
end
|
30
|
+
|
31
|
+
def dev_tools_enabled?
|
32
|
+
!!dev_tools_enabled
|
33
|
+
end
|
14
34
|
end
|
15
35
|
end
|
16
36
|
end
|
@@ -2,8 +2,13 @@ module Accountability
|
|
2
2
|
class Engine < ::Rails::Engine
|
3
3
|
isolate_namespace Accountability
|
4
4
|
|
5
|
-
ActiveSupport.on_load
|
5
|
+
ActiveSupport.on_load :active_record do
|
6
6
|
include Extensions
|
7
|
+
include Types
|
8
|
+
end
|
9
|
+
|
10
|
+
ActiveSupport.on_load :action_controller do
|
11
|
+
helper Accountability::BillingConfigurationsHelper
|
7
12
|
end
|
8
13
|
end
|
9
14
|
end
|
@@ -5,8 +5,19 @@ module Accountability
|
|
5
5
|
|
6
6
|
class_methods do
|
7
7
|
def acts_as_billable
|
8
|
+
after_create :create_default_account
|
9
|
+
|
8
10
|
has_many :accounts, as: :billable, class_name: 'Accountability::Account', dependent: :nullify
|
11
|
+
|
9
12
|
self.acts_as = acts_as.dup << :billable
|
13
|
+
|
14
|
+
define_method :create_default_account do
|
15
|
+
accounts.first_or_create
|
16
|
+
end
|
17
|
+
|
18
|
+
define_method :default_account do
|
19
|
+
accounts.first
|
20
|
+
end
|
10
21
|
end
|
11
22
|
end
|
12
23
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'active_support/core_ext/hash'
|
2
|
+
|
3
|
+
module ActionDispatch::Routing
|
4
|
+
class Mapper
|
5
|
+
def accountability_for(_tenants, options = {})
|
6
|
+
options[:controllers] ||= {}
|
7
|
+
options[:routes] ||= {}
|
8
|
+
|
9
|
+
options[:controllers].reverse_merge! default_accountability_controller_options
|
10
|
+
options[:routes].reverse_merge! default_accountability_route_options
|
11
|
+
|
12
|
+
options[:path_prefix] ||= options[:path] if options[:path_prefix].nil?
|
13
|
+
|
14
|
+
define_accountability_routes(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def define_accountability_routes(options)
|
18
|
+
cartographer = -> { accountability_routes(options) }
|
19
|
+
|
20
|
+
cartographer.call
|
21
|
+
Accountability::Engine.routes.draw(&cartographer)
|
22
|
+
end
|
23
|
+
|
24
|
+
def accountability_routes(options)
|
25
|
+
scope path: options[:path_prefix], as: :accountability do
|
26
|
+
resources :accounts, controller: options.dig(:controllers, :accounts), path: options.dig(:routes, :accounts) do
|
27
|
+
resources :billing_configurations, controller: options.dig(:controllers, :billing_configurations), path: options.dig(:routes, :billing_configurations) do
|
28
|
+
member { patch :designate_as_primary }
|
29
|
+
end
|
30
|
+
|
31
|
+
resources :payments, only: :create, controller: 'accountability/payments', path: 'payments'
|
32
|
+
resources :statements, only: [], controller: 'accountability/statements', path: 'statements' do
|
33
|
+
member { get :download_pdf }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
resources :products, controller: options.dig(:controllers, :products), path: options.dig(:routes, :products)
|
38
|
+
|
39
|
+
resources :order_groups, controller: options.dig(:controllers, :order_groups), path: options.dig(:routes, :order_groups) do
|
40
|
+
member { post :add_item }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
unscoped_direct(:stripe_v3_javascript) { 'https://js.stripe.com/v3/' }
|
45
|
+
end
|
46
|
+
|
47
|
+
def default_accountability_controller_options
|
48
|
+
{
|
49
|
+
accounts: 'accountability/accounts',
|
50
|
+
products: 'accountability/products',
|
51
|
+
order_groups: 'accountability/order_groups',
|
52
|
+
billing_configurations: 'accountability/billing_configurations'
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def default_accountability_route_options
|
57
|
+
{
|
58
|
+
accounts: 'accounts',
|
59
|
+
products: 'products',
|
60
|
+
order_groups: 'orders',
|
61
|
+
billing_configurations: 'billing_configurations'
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
# Mimic the functionality of Mapper#direct so that we can add a "direct" route from the cartographer proc even
|
66
|
+
# though we are in a scope because of #isolate_namespace.
|
67
|
+
# https://github.com/rails/rails/blob/6-0-stable/actionpack/lib/action_dispatch/routing/mapper.rb#L2119-L2125
|
68
|
+
def unscoped_direct(name, options = {}, &block)
|
69
|
+
@set.add_url_helper(name, options, &block)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'active_merchant'
|
2
|
+
require_dependency 'accountability/types/billing_configuration_types'
|
3
|
+
|
4
|
+
module Accountability
|
5
|
+
module Types
|
6
|
+
include BillingConfigurationTypes
|
7
|
+
ActiveRecord::Type.register(:billing_address, Accountability::Types::BillingAddressType)
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Accountability
|
2
|
+
module Types
|
3
|
+
module BillingConfigurationTypes
|
4
|
+
class BillingAddress
|
5
|
+
include ActiveModel::Model
|
6
|
+
include ActiveModel::Attributes
|
7
|
+
|
8
|
+
attribute :address_1, :string
|
9
|
+
attribute :address_2, :string
|
10
|
+
attribute :zip, :integer
|
11
|
+
attribute :city, :string
|
12
|
+
attribute :state, :string
|
13
|
+
attribute :country, :string
|
14
|
+
|
15
|
+
validates :address_1, :city, :state, :country, presence: true
|
16
|
+
validates :zip, numericality: { only_integer: true }
|
17
|
+
end
|
18
|
+
|
19
|
+
class BillingAddressType < ActiveModel::Type::Value
|
20
|
+
def type
|
21
|
+
:text
|
22
|
+
end
|
23
|
+
|
24
|
+
def cast_value(value)
|
25
|
+
case value
|
26
|
+
when String
|
27
|
+
decoded_value = ActiveSupport::JSON.decode(value)
|
28
|
+
BillingAddress.new(decoded_value)
|
29
|
+
when Hash
|
30
|
+
BillingAddress.new(value)
|
31
|
+
when BillingAddress
|
32
|
+
value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Only serialize the attributes that we have defined
|
37
|
+
# and keep extraneous things like "errors" or
|
38
|
+
# "validation_context" from slipping into the database.
|
39
|
+
def serialize(data)
|
40
|
+
case data
|
41
|
+
when Hash
|
42
|
+
billing_address = BillingAddress.new(data)
|
43
|
+
ActiveSupport::JSON.encode(billing_address.attributes)
|
44
|
+
when BillingAddress
|
45
|
+
ActiveSupport::JSON.encode(data.attributes)
|
46
|
+
else
|
47
|
+
super(data)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def changed_in_place?(raw_old_value, new_value)
|
52
|
+
cast_value(raw_old_value) != new_value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
module Accountability
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
# Executes with: `rails generate accountability:install`
|
7
|
+
# Note: All public instance methods will be called sequentially
|
8
|
+
|
9
|
+
include ActiveRecord::Generators::Migration
|
10
|
+
source_root File.join(__dir__, 'templates')
|
11
|
+
|
12
|
+
# def create_initializer_file
|
13
|
+
# initializer_content = "Accountability.configure { |_config| }"
|
14
|
+
# create_file "config/initializers/accountability.rb", initializer_content
|
15
|
+
# end
|
16
|
+
|
17
|
+
def copy_migration
|
18
|
+
# Note: migration.rb is always up-to-date
|
19
|
+
if fresh_installation?
|
20
|
+
destination = 'db/migrate/create_accountability_tables.rb'
|
21
|
+
migration_template 'migration.rb', destination, migration_version: migration_version
|
22
|
+
return true
|
23
|
+
end
|
24
|
+
|
25
|
+
# Existing applications may need new migration files
|
26
|
+
if missing_price_overrides?
|
27
|
+
destination = 'db/migrate/create_accountability_price_overrides_tables.rb'
|
28
|
+
migration_template 'price_overrides_migration.rb', destination, migration_version: migration_version
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def migration_version
|
33
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def fresh_installation?
|
39
|
+
!ActiveRecord::Base.connection.table_exists?('accountability_accounts')
|
40
|
+
end
|
41
|
+
|
42
|
+
def missing_price_overrides?
|
43
|
+
!ActiveRecord::Base.connection.table_exists?('accountability_price_overrides')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|