billing 0.0.0 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/billing/accounts.js +2 -0
  3. data/app/assets/javascripts/billing/charges.js +2 -0
  4. data/app/assets/javascripts/billing/modifiers.js +2 -0
  5. data/app/assets/javascripts/billing/payments.js +2 -0
  6. data/app/assets/stylesheets/billing/accounts.css +4 -0
  7. data/app/assets/stylesheets/billing/charges.css +4 -0
  8. data/app/assets/stylesheets/billing/modifiers.css +4 -0
  9. data/app/assets/stylesheets/billing/payments.css +4 -0
  10. data/app/controllers/billing/accounts_controller.rb +29 -0
  11. data/app/controllers/billing/application_controller.rb +18 -0
  12. data/app/controllers/billing/charges_controller.rb +29 -0
  13. data/app/controllers/billing/modifiers_controller.rb +29 -0
  14. data/app/controllers/billing/payments_controller.rb +29 -0
  15. data/app/helpers/billing/accounts_helper.rb +4 -0
  16. data/app/helpers/billing/charges_helper.rb +4 -0
  17. data/app/helpers/billing/modifiers_helper.rb +4 -0
  18. data/app/helpers/billing/payments_helper.rb +4 -0
  19. data/app/models/billing/account.rb +66 -0
  20. data/app/models/billing/account_item.rb +15 -0
  21. data/app/models/billing/charge.rb +21 -0
  22. data/app/models/billing/modifier.rb +32 -0
  23. data/app/models/billing/modifier_items.rb +11 -0
  24. data/app/models/billing/origin.rb +4 -0
  25. data/app/models/billing/payment.rb +39 -0
  26. data/app/models/billing/payment_type.rb +6 -0
  27. data/app/models/billing/payment_with_type.rb +14 -0
  28. data/app/models/billing/plu.rb +4 -0
  29. data/app/models/billing/profile.rb +4 -0
  30. data/app/models/billing/tax_group.rb +4 -0
  31. data/app/views/billing/accounts/index.html.erb +7 -0
  32. data/app/views/billing/accounts/new.html.erb +8 -0
  33. data/app/views/billing/accounts/show.html.erb +29 -0
  34. data/app/views/billing/application/index.html.erb +3 -0
  35. data/app/views/billing/charges/new.html.erb +12 -0
  36. data/app/views/billing/modifiers/new.html.erb +18 -0
  37. data/app/views/billing/payments/new.html.erb +11 -0
  38. data/config/routes.rb +6 -0
  39. data/db/migrate/20140717180443_create_billing_accounts.rb +9 -0
  40. data/db/migrate/20140717181134_create_billing_charges.rb +11 -0
  41. data/db/migrate/20140717181406_create_billing_discounts.rb +11 -0
  42. data/db/migrate/20140717183129_create_billing_payments.rb +10 -0
  43. data/db/migrate/20140717202527_create_billing_origins.rb +9 -0
  44. data/db/migrate/20140718164841_add_sumaries_to_billing_account.rb +11 -0
  45. data/db/migrate/20140718210349_add_fixed_value_to_billing_discount.rb +7 -0
  46. data/db/migrate/20140718212116_create_billing_payment_types.rb +11 -0
  47. data/db/migrate/20140719094023_create_billing_tax_groups.rb +9 -0
  48. data/db/migrate/20140719094033_create_billing_plus.rb +9 -0
  49. data/db/migrate/20140719094418_create_billing_profiles.rb +9 -0
  50. data/db/migrate/20140719103621_rename_billing_discounts_to_modifiers.rb +5 -0
  51. data/db/migrate/20140719110412_add_surcharges_sum_to_billing_account.rb +7 -0
  52. data/db/migrate/20140720110811_add_type_to_billing_payment.rb +6 -0
  53. data/db/migrate/20140720132559_add_type_to_billing_payment_type.rb +5 -0
  54. data/lib/billing.rb +16 -0
  55. data/lib/billing/billable.rb +34 -0
  56. data/lib/billing/engine.rb +1 -0
  57. data/lib/billing/mapping.rb +32 -0
  58. data/lib/billing/routes.rb +16 -0
  59. data/lib/billing/version.rb +1 -1
  60. data/lib/tasks/billing.rake +7 -0
  61. data/test/controllers/billing/accounts_controller_test.rb +19 -0
  62. data/test/controllers/billing/charges_controller_test.rb +16 -0
  63. data/test/controllers/billing/modifiers_controller_test.rb +16 -0
  64. data/test/controllers/billing/payments_controller_test.rb +16 -0
  65. data/test/dummy/app/models/profile.rb +3 -0
  66. data/test/dummy/config/routes.rb +3 -2
  67. data/test/dummy/db/development.sqlite3 +0 -0
  68. data/test/dummy/db/migrate/20140718104656_create_profiles.rb +8 -0
  69. data/test/dummy/db/schema.rb +112 -0
  70. data/test/dummy/db/test.sqlite3 +0 -0
  71. data/test/dummy/log/development.log +1602 -0
  72. data/test/dummy/log/test.log +52069 -0
  73. data/test/dummy/test/fixtures/profiles.yml +11 -0
  74. data/test/dummy/test/models/profile_test.rb +7 -0
  75. data/test/dummy/tmp/cache/assets/test/sprockets/02adf8ace512aefc4ef19b35aebc07f7 +0 -0
  76. data/test/dummy/tmp/cache/assets/test/sprockets/0cab887466527f5353fd43adab72769b +0 -0
  77. data/test/dummy/tmp/cache/assets/test/sprockets/25b7c6efcbd128f109577104af58d084 +0 -0
  78. data/test/dummy/tmp/cache/assets/test/sprockets/2f52090f9e08ac02cd453b04af0df887 +0 -0
  79. data/test/dummy/tmp/cache/assets/test/sprockets/35a523ac3c33d6409a69faead4b2a882 +0 -0
  80. data/test/dummy/tmp/cache/assets/test/sprockets/3f4fc67be1dd91962f5a0026848dca77 +0 -0
  81. data/test/dummy/tmp/cache/assets/test/sprockets/43b3cc0ac6f63c0e1a3ab61fec84519d +0 -0
  82. data/test/dummy/tmp/cache/assets/test/sprockets/59435066fc40e1ef5b45b0fd2c0eacf9 +0 -0
  83. data/test/dummy/tmp/cache/assets/test/sprockets/69cb965e6031d8099c185256f6fa8f90 +0 -0
  84. data/test/dummy/tmp/cache/assets/test/sprockets/6d34e4addaf3495d1d96306d164feb97 +0 -0
  85. data/test/dummy/tmp/cache/assets/test/sprockets/79316f9f3f5ebcec9b368d92d2e97e23 +0 -0
  86. data/test/dummy/tmp/cache/assets/test/sprockets/7ffc7e805e3fc08bae6a93e027a3e911 +0 -0
  87. data/test/dummy/tmp/cache/assets/test/sprockets/82ae0f4fbceb673c729b9bcb54a1161c +0 -0
  88. data/test/dummy/tmp/cache/assets/test/sprockets/9509747efe602f6a81d50d9744f385f2 +0 -0
  89. data/test/dummy/tmp/cache/assets/test/sprockets/971b6b8d6c7a57e72d235e55537a2c44 +0 -0
  90. data/test/dummy/tmp/cache/assets/test/sprockets/b68d1e1a967e74abe3e10f643756ae67 +0 -0
  91. data/test/dummy/tmp/cache/assets/test/sprockets/cab3eca4515d1263ea8db2ff58df151d +0 -0
  92. data/test/dummy/tmp/cache/assets/test/sprockets/cac68bb014ecc482b8f85312e49baa6f +0 -0
  93. data/test/dummy/tmp/cache/assets/test/sprockets/d3ab844c61f1c211ed5fad5407cd18ef +0 -0
  94. data/test/dummy/tmp/cache/assets/test/sprockets/d6d844128e4910cf773d1c48dd147e3b +0 -0
  95. data/test/dummy/tmp/cache/assets/test/sprockets/e62907e54633a2adb53c33c1f59b79bf +0 -0
  96. data/test/dummy/tmp/cache/assets/test/sprockets/e96b4e8fe0ebcceb51d202c8af7826ea +0 -0
  97. data/test/dummy/tmp/cache/assets/test/sprockets/eb95e26896c1c6788657c4ef68a7e9e1 +0 -0
  98. data/test/dummy/tmp/cache/assets/test/sprockets/efaa0abeb4ad44b0ef8df996631f3997 +0 -0
  99. data/test/dummy/tmp/cache/assets/test/sprockets/f393277b28dd79320611f18a379dbea7 +0 -0
  100. data/test/dummy/tmp/cache/assets/test/sprockets/fbf1489a0c3d66a329f070c10cd77a03 +0 -0
  101. data/test/fixtures/billing/accounts.yml +11 -0
  102. data/test/fixtures/billing/charges.yml +15 -0
  103. data/test/fixtures/billing/modifiers.yml +14 -0
  104. data/test/fixtures/billing/origins.yml +7 -0
  105. data/test/fixtures/billing/payment_types.yml +11 -0
  106. data/test/fixtures/billing/payments.yml +15 -0
  107. data/test/fixtures/billing/plus.yml +7 -0
  108. data/test/fixtures/billing/profiles.yml +7 -0
  109. data/test/fixtures/billing/tax_groups.yml +7 -0
  110. data/test/fixtures/profiles.yml +1 -0
  111. data/test/helpers/billing/accounts_helper_test.rb +6 -0
  112. data/test/helpers/billing/charges_helper_test.rb +6 -0
  113. data/test/helpers/billing/modifiers_helper_test.rb +6 -0
  114. data/test/helpers/billing/payments_helper_test.rb +6 -0
  115. data/test/models/billing/account_test.rb +43 -0
  116. data/test/models/billing/charge_test.rb +17 -0
  117. data/test/models/billing/modifier_test.rb +19 -0
  118. data/test/models/billing/origin_test.rb +9 -0
  119. data/test/models/billing/payment_test.rb +17 -0
  120. data/test/models/billing/payment_type_test.rb +9 -0
  121. data/test/models/billing/plu_test.rb +9 -0
  122. data/test/models/billing/profile_test.rb +9 -0
  123. data/test/models/billing/tax_group_test.rb +9 -0
  124. data/test/test_helper.rb +28 -2
  125. metadata +199 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5aa137f6c716e99d88ef6db1a1410aabc8c26b96
4
- data.tar.gz: fa42f7b09a684b283cf3caf489d42831c234d791
3
+ metadata.gz: 747d5529859b70e9cc69f11653785d07d55b74a4
4
+ data.tar.gz: cfc4af81e2d5e2361a2bea947e7e2bb3cdc251f2
5
5
  SHA512:
6
- metadata.gz: aed8c76f8a207cdf0fa32ced918be5a6373ef3f8aa428dc3e3c8db1bac8302435c047655e30ffbcfe27dc9214eba0c896d69ec39765cba03ac0182edd75cc62d
7
- data.tar.gz: a5c268cfdc08100fc98ba92f83a6ef752b9847a1b496b5fb53a564e8c99b3a28ea560543789b09118f9a8fd8f0209005c05e8bbadf1aa6848813caeca6eab88a
6
+ metadata.gz: c6c723a641929e19b86cd4bbfd1e175606036f055ba0112691c82c5e573b08bbc411133c6c577aef41655859e85a100a26b5ed60ed3c6e7bd8a6f3c6d9b7f535
7
+ data.tar.gz: c6d5372d0418f727050175f5eddf78c67f2cf903545722a593e4c9a6bb2bab8342c769cfd9a4d21a3741ed40053dfa4d3d341483ad157606e83c3381b72bebdf
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,29 @@
1
+ require_dependency "billing/application_controller"
2
+
3
+ module Billing
4
+ class AccountsController < ApplicationController
5
+ before_action :set_account, except: [:index, :new, :create]
6
+
7
+ def index
8
+ @accounts = billable.billing_accounts
9
+ end
10
+
11
+ def new
12
+ @account = billable.billing_accounts.new
13
+ end
14
+
15
+ def create
16
+ @account = billable.billing_accounts.new
17
+ if @account.save
18
+ redirect_to @account
19
+ else
20
+ render action: :new
21
+ end
22
+ end
23
+
24
+ private
25
+ def set_account
26
+ @account = billable.billing_accounts.find(params[:id])
27
+ end
28
+ end
29
+ end
@@ -1,4 +1,22 @@
1
1
  module Billing
2
2
  class ApplicationController < ActionController::Base
3
+ prepend_before_filter :include_extra_module
4
+ helper_method :billable
5
+
6
+ def index
7
+ end
8
+
9
+ def billable
10
+ @billable ||= billing_mapping.i_klass.find_by(billing_mapping.i_find_key => params[billing_mapping.i_param])
11
+ end
12
+
13
+ private
14
+ def billing_mapping
15
+ @billing_mapping ||= Billing::Mapping.find(request.fullpath)
16
+ end
17
+
18
+ def include_extra_module
19
+ self.class.send(:include, billing_mapping.i_extra_module) if billing_mapping.i_extra_module.present?
20
+ end
3
21
  end
4
22
  end
@@ -0,0 +1,29 @@
1
+ require_dependency "billing/application_controller"
2
+
3
+ module Billing
4
+ class ChargesController < ApplicationController
5
+ before_action :set_account
6
+
7
+ def new
8
+ @charge = @account.charges.new
9
+ end
10
+
11
+ def create
12
+ @charge = @account.charges.new(charge_params)
13
+ if @charge.save
14
+ redirect_to @account
15
+ else
16
+ render action: :new
17
+ end
18
+ end
19
+
20
+ private
21
+ def set_account
22
+ @account = billable.billing_accounts.find(params[:account_id])
23
+ end
24
+
25
+ def charge_params
26
+ params.require(:charge).permit(:price)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ require_dependency "billing/application_controller"
2
+
3
+ module Billing
4
+ class ModifiersController < ApplicationController
5
+ before_action :set_account
6
+
7
+ def new
8
+ @modifier = @account.modifiers.new
9
+ end
10
+
11
+ def create
12
+ @modifier = @account.modifiers.new(modifier_params)
13
+ if @modifier.save
14
+ redirect_to @account
15
+ else
16
+ render action: :new
17
+ end
18
+ end
19
+
20
+ private
21
+ def set_account
22
+ @account = billable.billing_accounts.find(params[:account_id])
23
+ end
24
+
25
+ def modifier_params
26
+ params.require(:modifier).permit(:percent_ratio, :fixed_value, :charge_id)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ require_dependency "billing/application_controller"
2
+
3
+ module Billing
4
+ class PaymentsController < ApplicationController
5
+ before_action :set_account
6
+
7
+ def new
8
+ @payment = @account.payments.new(value: @account.total)
9
+ end
10
+
11
+ def create
12
+ @payment = @account.payments.new(payment_params)
13
+ if @payment.save
14
+ redirect_to @account
15
+ else
16
+ render action: :new
17
+ end
18
+ end
19
+
20
+ private
21
+ def set_account
22
+ @account = billable.billing_accounts.find(params[:account_id])
23
+ end
24
+
25
+ def payment_params
26
+ params.require(:payment).permit(:value)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,4 @@
1
+ module Billing
2
+ module AccountsHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Billing
2
+ module ChargesHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Billing
2
+ module ModifiersHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Billing
2
+ module PaymentsHelper
3
+ end
4
+ end
@@ -0,0 +1,66 @@
1
+ module Billing
2
+ class Account < ActiveRecord::Base
3
+ monetize :charges_sum_cents
4
+ monetize :discounts_sum_cents
5
+ monetize :surcharges_sum_cents
6
+ monetize :payments_sum_cents
7
+ monetize :total_cents
8
+ monetize :balance_cents
9
+
10
+ belongs_to :billable, polymorphic: true
11
+ has_many :charges, inverse_of: :account
12
+ has_many :modifiers, inverse_of: :account
13
+ has_many :payments, inverse_of: :account
14
+
15
+ accepts_nested_attributes_for :charges, :modifiers, :payments
16
+
17
+ before_validation :update_sumaries
18
+
19
+ validates_numericality_of :total, greater_than_or_equal_to: 0
20
+
21
+ def charge(*args)
22
+ c = charges.new Charge.args(*args)
23
+ c if c.save
24
+ end
25
+
26
+ def modify(*args)
27
+ m = modifiers.new Modifier.args(*args)
28
+ m if m.save
29
+ end
30
+
31
+ def pay(*args)
32
+ p = payments.new Payment.args(*args)
33
+ p if p.save
34
+ end
35
+
36
+ def modifier_items
37
+ calculate_modifiers
38
+ end
39
+
40
+ def payment_types
41
+ billable.try(:billing_payment_types) || billable.try(:payment_types) || []
42
+ end
43
+
44
+ private
45
+ def calculate_modifiers
46
+ @modifier_items = ModifierItems.new.tap() do |items|
47
+ modifiers.each do |modifier|
48
+ if charge = modifier.charge
49
+ items << Charge.new(price: modifier.percent_ratio.nil? ? modifier.fixed_value : (charge.price * modifier.percent_ratio), chargable: charge)
50
+ else
51
+ items << Charge.new(price: modifier.percent_ratio.nil? ? modifier.fixed_value : (charges.to_a.sum(&:price).to_money * modifier.percent_ratio))
52
+ end
53
+ end
54
+ end
55
+ end
56
+ def update_sumaries
57
+ self.charges_sum = charges.to_a.sum(&:price).to_money
58
+ calculate_modifiers
59
+ self.discounts_sum = -@modifier_items.discounts.sum(&:price).to_money
60
+ self.surcharges_sum = @modifier_items.surcharges.sum(&:price).to_money
61
+ self.payments_sum = payments.to_a.sum(&:value).to_money
62
+ self.total = charges_sum + surcharges_sum - discounts_sum
63
+ self.balance = payments_sum - total
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,15 @@
1
+ module Billing
2
+ module AccountItem
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ #belongs_to :account
7
+
8
+ delegate :save, to: :account, prefix: :account
9
+ after_save :account_save
10
+
11
+ validates_presence_of :account
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ module Billing
2
+ class Charge < ActiveRecord::Base
3
+ include AccountItem
4
+ belongs_to :account, inverse_of: :charges, validate: true
5
+ belongs_to :chargable, polymorphic: true
6
+ monetize :price_cents
7
+
8
+ validates_presence_of :price
9
+
10
+ class << self
11
+ def args(*args)
12
+ case when args.blank? || args.first.is_a?(Hash) then
13
+ {}.merge(*args)
14
+ else
15
+ h = { price: args.shift.to_money }
16
+ args.any? ? h.merge(*args) : h
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,32 @@
1
+ module Billing
2
+ class Modifier < ActiveRecord::Base
3
+ include AccountItem
4
+ belongs_to :account, inverse_of: :modifiers, validate: true
5
+ belongs_to :charge
6
+ monetize :fixed_value_cents
7
+
8
+ validate :percent_or_value
9
+
10
+ private
11
+ def percent_or_value
12
+ errors.add :percent_or_value, I18n.t('errors.messages.blank') if percent_ratio.blank? and fixed_value.zero?
13
+ errors.add :percent_or_value, I18n.t('errors.messages.present') if percent_ratio.present? and !fixed_value.zero?
14
+ end
15
+
16
+ class << self
17
+ def args(*args)
18
+ case when args.blank? || args.first.kind_of?(Hash) then
19
+ {}.merge(*args)
20
+ when args.first.kind_of?(String) then
21
+ d = args.shift
22
+ if d.index('%')
23
+ #TODO parse
24
+ end
25
+ else
26
+ h = { fixed_value: args.shift.to_money }
27
+ args.any? ? h.merge(*args) : h
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ module Billing
2
+ class ModifierItems < Array
3
+ def discounts
4
+ select{ |m| m.price < 0 }
5
+ end
6
+
7
+ def surcharges
8
+ select{ |m| m.price > 0 }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ module Billing
2
+ class Origin < ActiveRecord::Base
3
+ end
4
+ end
@@ -0,0 +1,39 @@
1
+ module Billing
2
+ class Payment < ActiveRecord::Base
3
+ include AccountItem
4
+ belongs_to :account, inverse_of: :payments, validate: true
5
+
6
+ monetize :value_cents
7
+
8
+ delegate :billable, to: :account
9
+
10
+ validates_presence_of :value
11
+
12
+ after_initialize on: :create do
13
+ self.value = -account.try(:balance).to_money if value.zero?
14
+ end
15
+
16
+ class << self
17
+ def args(*args)
18
+ h = { type: 'Billing::PaymentWithType' }
19
+ case when args.blank? || args.first.kind_of?(Hash) then
20
+ args.blank? ? h : h.merge(*args)
21
+ when args.first.kind_of?(String) then
22
+ #TODO parse
23
+ else
24
+ h.merge!(payment_type_id: args.shift.to_param)
25
+ if args.any? && (args.first.kind_of?(Hash) || args.first.kind_of?(String))
26
+ h.merge(args(*args))
27
+ else
28
+ if args.blank?
29
+ h
30
+ else
31
+ h.merge!( value: args.shift.to_money )
32
+ args.any? ? h.merge(*args) : h
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,6 @@
1
+ module Billing
2
+ class PaymentType < ActiveRecord::Base
3
+ has_many :payments
4
+ validates_presence_of :name
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ module Billing
2
+ class PaymentWithType < Payment
3
+ belongs_to :payment_type, inverse_of: :payments
4
+ delegate :payment_types, to: :account
5
+
6
+ validates_presence_of :payment_type
7
+ validates :payment_type, inclusion: { in: :payment_types }
8
+
9
+ after_initialize on: :create do
10
+ self.payment_type = billable.try(:default_payment_type) unless payment_type
11
+ end
12
+
13
+ end
14
+ end