kaui 0.5.3 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +6 -4
- data/Gemfile.lock +30 -30
- data/README.md +2 -2
- data/app/controllers/kaui/accounts_controller.rb +29 -4
- data/app/controllers/kaui/bundles_controller.rb +4 -2
- data/app/controllers/kaui/chargebacks_controller.rb +23 -1
- data/app/controllers/kaui/credits_controller.rb +4 -4
- data/app/controllers/kaui/payment_methods_controller.rb +27 -8
- data/app/controllers/kaui/subscriptions_controller.rb +1 -8
- data/app/helpers/kaui/killbill_helper.rb +39 -52
- data/app/views/kaui/account_timelines/show.html.erb +2 -2
- data/app/views/kaui/accounts/index.html.erb +28 -13
- data/app/views/kaui/chargebacks/new.html.erb +8 -0
- data/app/views/kaui/payment_methods/index.html.erb +26 -13
- data/app/views/kaui/subscriptions/_subscriptions_table.html.erb +4 -4
- data/app/views/kaui/subscriptions/edit.html.erb +1 -1
- data/config/routes.rb +6 -0
- data/kaui.gemspec +1 -1
- data/lib/kaui/version.rb +1 -1
- data/test/test_helper.rb +4 -0
- metadata +13 -38
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dea19b00bc9a01b365d3a39fd237ad88b2d0cc34
|
4
|
+
data.tar.gz: 738868e5c83c65c4c76e29c7395b71944c3f12f0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f86d0958d9a8c1bb23c02d980ba8e958020c7fc0459d908f52d023e7a8cf8ada252bc8df233517a599ae4c0d47875f4d804f08f32fce97a0c1e91451c43d5494
|
7
|
+
data.tar.gz: a0a3708bd8116f351612b0a0e3e856747fdb78a50b6ca3048f9a1d947c1e8125cef955436b4537fc75eed41c831148d78907ff1e158f923272ef01e8c8525477
|
data/.travis.yml
CHANGED
@@ -2,19 +2,21 @@ language: ruby
|
|
2
2
|
|
3
3
|
notifications:
|
4
4
|
email:
|
5
|
-
-
|
5
|
+
- kill-bill-commits@googlegroups.com
|
6
6
|
|
7
7
|
rvm:
|
8
|
-
- 1.9.3
|
9
8
|
- 1.9.2
|
10
|
-
-
|
9
|
+
- 1.9.3
|
10
|
+
- 2.0.0
|
11
11
|
- ruby-head
|
12
|
+
- jruby-19mode
|
13
|
+
- jruby-20mode
|
12
14
|
- jruby-head
|
13
15
|
|
14
16
|
jdk:
|
17
|
+
- openjdk6
|
15
18
|
- openjdk7
|
16
19
|
- oraclejdk7
|
17
|
-
- openjdk6
|
18
20
|
|
19
21
|
before_script:
|
20
22
|
- mysql -e 'create database kaui_test;'
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
kaui (0.
|
4
|
+
kaui (0.6.0)
|
5
5
|
cancan (~> 1.6.10)
|
6
6
|
d3_rails (~> 3.2.8)
|
7
7
|
devise (~> 3.0.2)
|
8
8
|
jquery-rails (~> 3.0.4)
|
9
|
-
killbill-client (~> 0.
|
9
|
+
killbill-client (~> 0.5.1)
|
10
10
|
money-rails (~> 0.8.1)
|
11
11
|
rails (~> 3.2.14)
|
12
12
|
rest-client (~> 1.6.7)
|
@@ -14,12 +14,12 @@ PATH
|
|
14
14
|
GEM
|
15
15
|
remote: http://rubygems.org/
|
16
16
|
specs:
|
17
|
-
actionmailer (3.2.
|
18
|
-
actionpack (= 3.2.
|
17
|
+
actionmailer (3.2.15)
|
18
|
+
actionpack (= 3.2.15)
|
19
19
|
mail (~> 2.5.4)
|
20
|
-
actionpack (3.2.
|
21
|
-
activemodel (= 3.2.
|
22
|
-
activesupport (= 3.2.
|
20
|
+
actionpack (3.2.15)
|
21
|
+
activemodel (= 3.2.15)
|
22
|
+
activesupport (= 3.2.15)
|
23
23
|
builder (~> 3.0.0)
|
24
24
|
erubis (~> 2.7.0)
|
25
25
|
journey (~> 1.0.4)
|
@@ -27,18 +27,18 @@ GEM
|
|
27
27
|
rack-cache (~> 1.2)
|
28
28
|
rack-test (~> 0.6.1)
|
29
29
|
sprockets (~> 2.2.1)
|
30
|
-
activemodel (3.2.
|
31
|
-
activesupport (= 3.2.
|
30
|
+
activemodel (3.2.15)
|
31
|
+
activesupport (= 3.2.15)
|
32
32
|
builder (~> 3.0.0)
|
33
|
-
activerecord (3.2.
|
34
|
-
activemodel (= 3.2.
|
35
|
-
activesupport (= 3.2.
|
33
|
+
activerecord (3.2.15)
|
34
|
+
activemodel (= 3.2.15)
|
35
|
+
activesupport (= 3.2.15)
|
36
36
|
arel (~> 3.0.2)
|
37
37
|
tzinfo (~> 0.3.29)
|
38
|
-
activeresource (3.2.
|
39
|
-
activemodel (= 3.2.
|
40
|
-
activesupport (= 3.2.
|
41
|
-
activesupport (3.2.
|
38
|
+
activeresource (3.2.15)
|
39
|
+
activemodel (= 3.2.15)
|
40
|
+
activesupport (= 3.2.15)
|
41
|
+
activesupport (3.2.15)
|
42
42
|
i18n (~> 0.6, >= 0.6.4)
|
43
43
|
multi_json (~> 1.0)
|
44
44
|
arel (3.0.2)
|
@@ -59,8 +59,8 @@ GEM
|
|
59
59
|
jquery-rails (3.0.4)
|
60
60
|
railties (>= 3.0, < 5.0)
|
61
61
|
thor (>= 0.14, < 2.0)
|
62
|
-
json (1.8.
|
63
|
-
killbill-client (0.
|
62
|
+
json (1.8.1)
|
63
|
+
killbill-client (0.5.1)
|
64
64
|
json (~> 1.8.0)
|
65
65
|
mail (2.5.4)
|
66
66
|
mime-types (~> 1.16)
|
@@ -72,7 +72,7 @@ GEM
|
|
72
72
|
activesupport (>= 3.0)
|
73
73
|
money (~> 5.1.0)
|
74
74
|
railties (>= 3.0)
|
75
|
-
multi_json (1.8.
|
75
|
+
multi_json (1.8.2)
|
76
76
|
mysql2 (0.3.13)
|
77
77
|
orm_adapter (0.4.0)
|
78
78
|
polyglot (0.3.3)
|
@@ -83,17 +83,17 @@ GEM
|
|
83
83
|
rack
|
84
84
|
rack-test (0.6.2)
|
85
85
|
rack (>= 1.0)
|
86
|
-
rails (3.2.
|
87
|
-
actionmailer (= 3.2.
|
88
|
-
actionpack (= 3.2.
|
89
|
-
activerecord (= 3.2.
|
90
|
-
activeresource (= 3.2.
|
91
|
-
activesupport (= 3.2.
|
86
|
+
rails (3.2.15)
|
87
|
+
actionmailer (= 3.2.15)
|
88
|
+
actionpack (= 3.2.15)
|
89
|
+
activerecord (= 3.2.15)
|
90
|
+
activeresource (= 3.2.15)
|
91
|
+
activesupport (= 3.2.15)
|
92
92
|
bundler (~> 1.0)
|
93
|
-
railties (= 3.2.
|
94
|
-
railties (3.2.
|
95
|
-
actionpack (= 3.2.
|
96
|
-
activesupport (= 3.2.
|
93
|
+
railties (= 3.2.15)
|
94
|
+
railties (3.2.15)
|
95
|
+
actionpack (= 3.2.15)
|
96
|
+
activesupport (= 3.2.15)
|
97
97
|
rack-ssl (~> 1.3.2)
|
98
98
|
rake (>= 0.8.7)
|
99
99
|
rdoc (~> 3.4)
|
@@ -114,7 +114,7 @@ GEM
|
|
114
114
|
treetop (1.4.15)
|
115
115
|
polyglot
|
116
116
|
polyglot (>= 0.3.1)
|
117
|
-
tzinfo (0.3.
|
117
|
+
tzinfo (0.3.38)
|
118
118
|
warden (1.2.3)
|
119
119
|
rack (>= 1.0)
|
120
120
|
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ You can run Kaui locally using the sandbox script:
|
|
12
12
|
# Point to your killbill installation
|
13
13
|
export KILLBILL_URL="http://killbill.company.com:8080"
|
14
14
|
# Run the sandbox script
|
15
|
-
script/sandbox
|
15
|
+
bundle exec script/sandbox
|
16
16
|
# Start the Rails app
|
17
17
|
cd sandbox
|
18
18
|
rails s
|
@@ -49,7 +49,7 @@ Running tests
|
|
49
49
|
Go into 'test/dummy':
|
50
50
|
> cd test/dummy/
|
51
51
|
|
52
|
-
Run
|
52
|
+
Run migrations:
|
53
53
|
> export RAILS_ENV=test
|
54
54
|
> rake kaui:install:migrations
|
55
55
|
> rake db:migrate
|
@@ -5,6 +5,34 @@ class Kaui::AccountsController < Kaui::EngineController
|
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
|
+
def pagination
|
9
|
+
json = { :sEcho => params[:sEcho], :iTotalRecords => 0, :iTotalDisplayRecords => 0, :aaData => [] }
|
10
|
+
|
11
|
+
search_key = params[:sSearch]
|
12
|
+
if search_key.present?
|
13
|
+
accounts = Kaui::KillbillHelper::search_accounts(search_key, params[:iDisplayStart] || 0, params[:iDisplayLength] || 10, options_for_klient)
|
14
|
+
else
|
15
|
+
accounts = Kaui::KillbillHelper::get_accounts(params[:iDisplayStart] || 0, params[:iDisplayLength] || 10, options_for_klient)
|
16
|
+
end
|
17
|
+
json[:iTotalDisplayRecords] = accounts.pagination_total_nb_records
|
18
|
+
json[:iTotalRecords] = accounts.pagination_max_nb_records
|
19
|
+
|
20
|
+
accounts.each do |account|
|
21
|
+
json[:aaData] << [
|
22
|
+
view_context.link_to(account.account_id, view_context.url_for(:action => :show, :id => account.account_id)),
|
23
|
+
account.name,
|
24
|
+
account.external_key,
|
25
|
+
account.currency,
|
26
|
+
account.city,
|
27
|
+
account.country
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
respond_to do |format|
|
32
|
+
format.json { render :json => json }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
8
36
|
def show
|
9
37
|
@key = params[:id]
|
10
38
|
if @key.present?
|
@@ -32,10 +60,7 @@ class Kaui::AccountsController < Kaui::EngineController
|
|
32
60
|
@subscriptions_by_bundle_id = {}
|
33
61
|
|
34
62
|
@bundles.each do |bundle|
|
35
|
-
|
36
|
-
if subscriptions.present?
|
37
|
-
@subscriptions_by_bundle_id[bundle.bundle_id.to_s] = (@subscriptions_by_bundle_id[bundle.bundle_id.to_s] || []) + subscriptions
|
38
|
-
end
|
63
|
+
@subscriptions_by_bundle_id[bundle.bundle_id.to_s] = (@subscriptions_by_bundle_id[bundle.bundle_id.to_s] || []) + bundle.subscriptions
|
39
64
|
end
|
40
65
|
rescue => e
|
41
66
|
flash.now[:error] = "Error while retrieving account information for account: #{as_string(e)}"
|
@@ -13,17 +13,19 @@ class Kaui::BundlesController < Kaui::EngineController
|
|
13
13
|
@bundle = Kaui::KillbillHelper::get_bundle_by_key(key, params[:account_id], options_for_klient)
|
14
14
|
|
15
15
|
if @bundle.present?
|
16
|
-
@account = Kaui::KillbillHelper::
|
17
|
-
@subscriptions =
|
16
|
+
@account = Kaui::KillbillHelper::get_account(@bundle.account_id, false, false, options_for_klient)
|
17
|
+
@subscriptions = @bundle.subscriptions
|
18
18
|
else
|
19
19
|
flash.now[:error] = "Bundle #{key} not found"
|
20
20
|
render :action => :index
|
21
21
|
end
|
22
22
|
rescue => e
|
23
23
|
flash.now[:error] = "Error while retrieving bundle information for #{key}: #{as_string(e)}"
|
24
|
+
render :action => :index
|
24
25
|
end
|
25
26
|
else
|
26
27
|
flash.now[:error] = "No id given"
|
28
|
+
render :action => :index
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
@@ -41,14 +41,36 @@ class Kaui::ChargebacksController < Kaui::EngineController
|
|
41
41
|
|
42
42
|
def create
|
43
43
|
chargeback = Kaui::Chargeback.new(params[:chargeback])
|
44
|
+
should_cancel_subs = (params[:cancel_all_subs] == "1")
|
44
45
|
|
45
46
|
if chargeback.present?
|
46
47
|
begin
|
47
48
|
Kaui::KillbillHelper::create_chargeback(chargeback, current_user, params[:reason], params[:comment], options_for_klient)
|
48
|
-
flash[:notice] = "Chargeback created"
|
49
49
|
rescue => e
|
50
50
|
flash[:error] = "Error while creating a new chargeback: #{as_string(e)}"
|
51
|
+
redirect_to kaui_engine.account_timeline_path(:id => params[:account_id]) and return
|
51
52
|
end
|
53
|
+
|
54
|
+
# Cancel all subscriptions on the account, if required
|
55
|
+
if should_cancel_subs
|
56
|
+
begin
|
57
|
+
bundles = Kaui::KillbillHelper::get_bundles(params[:account_id], options_for_klient)
|
58
|
+
bundles.each do |bundle|
|
59
|
+
bundle.subscriptions.each do |subscription|
|
60
|
+
# Already cancelled?
|
61
|
+
next unless subscription.billing_end_date.blank?
|
62
|
+
|
63
|
+
# Cancel the entitlement immediately but use the default billing policy
|
64
|
+
Kaui::KillbillHelper::delete_subscription(subscription.subscription_id, current_user, params[:reason], params[:comment], 'IMMEDIATE', nil, options_for_klient)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
rescue => e
|
68
|
+
flash[:error] = "Error while cancelling subscriptions: #{as_string(e)}"
|
69
|
+
redirect_to kaui_engine.account_timeline_path(:id => params[:account_id]) and return
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
flash[:notice] = "Chargeback created"
|
52
74
|
else
|
53
75
|
flash[:error] = "No chargeback to process"
|
54
76
|
end
|
@@ -26,7 +26,7 @@ class Kaui::CreditsController < Kaui::EngineController
|
|
26
26
|
|
27
27
|
begin
|
28
28
|
@account = Kaui::KillbillHelper::get_account(@account_id, false, false, options_for_klient)
|
29
|
-
@invoice = Kaui::KillbillHelper::get_invoice(@invoice_id, true, options_for_klient) unless @invoice_id.nil?
|
29
|
+
@invoice = Kaui::KillbillHelper::get_invoice(@invoice_id, true, "NONE", options_for_klient) unless @invoice_id.nil?
|
30
30
|
rescue => e
|
31
31
|
flash.now[:error] = "Error while starting to create credit: #{as_string(e)}"
|
32
32
|
end
|
@@ -38,14 +38,14 @@ class Kaui::CreditsController < Kaui::EngineController
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def create
|
41
|
-
credit =
|
41
|
+
credit = params[:credit]
|
42
42
|
begin
|
43
43
|
Kaui::KillbillHelper::create_credit(credit, current_user, params[:reason], params[:comment], options_for_klient)
|
44
|
-
account = Kaui::KillbillHelper::get_account(credit
|
44
|
+
account = Kaui::KillbillHelper::get_account(credit['account_id'], false, false, options_for_klient)
|
45
45
|
flash[:notice] = "Credit created"
|
46
46
|
rescue => e
|
47
47
|
flash[:error] = "Error while starting to create credit: #{as_string(e)}"
|
48
48
|
end
|
49
|
-
redirect_to Kaui.account_home_path.call(credit
|
49
|
+
redirect_to Kaui.account_home_path.call(credit['account_id'])
|
50
50
|
end
|
51
51
|
end
|
@@ -2,14 +2,33 @@ require 'kaui/killbill_helper'
|
|
2
2
|
|
3
3
|
class Kaui::PaymentMethodsController < Kaui::EngineController
|
4
4
|
def index
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
end
|
6
|
+
|
7
|
+
def pagination
|
8
|
+
json = { :sEcho => params[:sEcho], :iTotalRecords => 0, :iTotalDisplayRecords => 0, :aaData => [] }
|
9
|
+
|
10
|
+
search_key = params[:sSearch]
|
11
|
+
if search_key.present?
|
12
|
+
payment_methods = Kaui::KillbillHelper::search_payment_methods(search_key, params[:iDisplayStart] || 0, params[:iDisplayLength] || 10, options_for_klient)
|
13
|
+
else
|
14
|
+
payment_methods = Kaui::KillbillHelper::get_payment_methods(params[:iDisplayStart] || 0, params[:iDisplayLength] || 10, options_for_klient)
|
15
|
+
end
|
16
|
+
json[:iTotalDisplayRecords] = payment_methods.pagination_total_nb_records
|
17
|
+
json[:iTotalRecords] = payment_methods.pagination_max_nb_records
|
18
|
+
|
19
|
+
payment_methods.each do |payment_method|
|
20
|
+
info_plugin = payment_method.plugin_info || OpenStruct.new
|
21
|
+
json[:aaData] << [
|
22
|
+
view_context.link_to(payment_method.account_id, view_context.url_for(:controller => :accounts, :action => :show, :id => payment_method.account_id)),
|
23
|
+
info_plugin.external_payment_id,
|
24
|
+
info_plugin.type,
|
25
|
+
info_plugin.cc_name,
|
26
|
+
info_plugin.cc_last4,
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
30
|
+
respond_to do |format|
|
31
|
+
format.json { render :json => json }
|
13
32
|
end
|
14
33
|
end
|
15
34
|
|
@@ -151,18 +151,11 @@ class Kaui::SubscriptionsController < Kaui::EngineController
|
|
151
151
|
end
|
152
152
|
|
153
153
|
def destroy
|
154
|
-
|
155
|
-
|
156
154
|
subscription_id = params[:id]
|
157
155
|
|
158
|
-
puts "calling destroy id = #{subscription_id}"
|
159
|
-
|
160
156
|
if subscription_id.present?
|
161
157
|
begin
|
162
|
-
|
163
|
-
puts "current_user = #{current_user}"
|
164
|
-
|
165
|
-
Kaui::KillbillHelper::delete_subscription(subscription_id, current_user, params[:reason], params[:comment], params[:policy], options_for_klient)
|
158
|
+
Kaui::KillbillHelper::delete_subscription(subscription_id, current_user, params[:reason], params[:comment], params[:policy], params[:policy], options_for_klient)
|
166
159
|
rescue => e
|
167
160
|
flash[:error] = "Error while canceling subscription: #{as_string(e)}"
|
168
161
|
end
|
@@ -71,6 +71,14 @@ module Kaui
|
|
71
71
|
|
72
72
|
############## ACCOUNT ##############
|
73
73
|
|
74
|
+
def self.get_accounts(offset, limit, options = {})
|
75
|
+
KillBillClient::Model::Account.find_in_batches offset, limit, false, false, options
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.search_accounts(search_key, offset, limit, options = {})
|
79
|
+
KillBillClient::Model::Account.find_in_batches_by_search_key search_key, offset, limit, false, false, options
|
80
|
+
end
|
81
|
+
|
74
82
|
def self.get_account_by_key_with_balance_and_cba(key, options = {})
|
75
83
|
self.get_account_by_key(key, false, true, options)
|
76
84
|
end
|
@@ -132,28 +140,24 @@ module Kaui
|
|
132
140
|
|
133
141
|
############## BUNDLE ##############
|
134
142
|
|
135
|
-
def self.get_bundle_by_key(key, account_id, options = {})
|
143
|
+
def self.get_bundle_by_key(key, account_id = nil, options = {})
|
136
144
|
# support id (UUID) and external key search
|
137
145
|
if key =~ /[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}/
|
138
|
-
|
146
|
+
Kaui::KillbillHelper::get_bundle(key, options)
|
139
147
|
else
|
140
|
-
|
148
|
+
raise ArgumentError.new("account id not specified") if account_id.blank?
|
149
|
+
bundles = KillBillClient::Model::Bundle.find_all_by_account_id_and_external_key account_id, key, options
|
150
|
+
bundles.empty? ? nil : bundles[-1]
|
141
151
|
end
|
142
152
|
end
|
143
153
|
|
144
154
|
def self.get_bundles(account_id, options = {})
|
145
|
-
|
146
|
-
|
147
|
-
end
|
148
|
-
|
149
|
-
def self.get_bundle_by_external_key(account_id, external_key, options = {})
|
150
|
-
data = call_killbill :get, "/1.0/kb/accounts/#{account_id}/bundles?externalKey=#{external_key}", options
|
151
|
-
process_response(data, :single) { |json| Kaui::Bundle.new(json) }
|
155
|
+
account = KillBillClient::Model::Account.find_by_id account_id, options
|
156
|
+
account.bundles
|
152
157
|
end
|
153
158
|
|
154
159
|
def self.get_bundle(bundle_id, options = {})
|
155
|
-
|
156
|
-
process_response(data, :single) { |json| Kaui::Bundle.new(json) }
|
160
|
+
KillBillClient::Model::Bundle::find_by_id(bundle_id, options)
|
157
161
|
end
|
158
162
|
|
159
163
|
def self.transfer_bundle(bundle_id, new_account_id, cancel_immediately = false, transfer_addons = true, current_user = nil, reason = nil, comment = nil, options = {})
|
@@ -165,27 +169,11 @@ module Kaui
|
|
165
169
|
|
166
170
|
############## SUBSCRIPTION ##############
|
167
171
|
|
168
|
-
def self.get_subscriptions_for_bundle(bundle_id, options = {})
|
169
|
-
data = call_killbill :get, "/1.0/kb/bundles/#{bundle_id}/subscriptions", options
|
170
|
-
process_response(data, :multiple) { |json| Kaui::Subscription.new(json) }
|
171
|
-
end
|
172
|
-
|
173
|
-
def self.get_subscriptions(account_id, options = {})
|
174
|
-
subscriptions = []
|
175
|
-
bundles = get_bundles(account_id)
|
176
|
-
bundles.each do |bundle|
|
177
|
-
subscriptions += get_subscriptions_for_bundle(bundle.bundle_id)
|
178
|
-
end
|
179
|
-
subscriptions
|
180
|
-
end
|
181
|
-
|
182
172
|
def self.get_subscription(subscription_id, options = {})
|
183
|
-
|
184
|
-
process_response(data, :single) { |json| Kaui::Subscription.new(json) }
|
173
|
+
KillBillClient::Model::Subscription::find_by_id(subscription_id, options)
|
185
174
|
end
|
186
175
|
|
187
176
|
def self.create_subscription(subscription, current_user = nil, reason = nil, comment = nil, options = {})
|
188
|
-
|
189
177
|
entitlement = KillBillClient::Model::Subscription.new
|
190
178
|
entitlement.account_id = subscription.account_id
|
191
179
|
entitlement.bundle_id = subscription.bundle_id
|
@@ -195,12 +183,10 @@ module Kaui
|
|
195
183
|
entitlement.billing_period = subscription.billing_period
|
196
184
|
entitlement.price_list = subscription.price_list
|
197
185
|
|
198
|
-
|
199
186
|
entitlement.create(extract_created_by(current_user), extract_reason_code(reason), comment, options)
|
200
187
|
end
|
201
188
|
|
202
189
|
def self.update_subscription(subscription, requested_date = nil, policy = nil, current_user = nil, reason = nil, comment = nil, options = {})
|
203
|
-
|
204
190
|
requested_date = requested_date.to_s unless requested_date.blank?
|
205
191
|
entitlement = KillBillClient::Model::Subscription.new
|
206
192
|
entitlement.subscription_id = subscription.subscription_id
|
@@ -208,12 +194,10 @@ module Kaui
|
|
208
194
|
extract_created_by(current_user), extract_reason_code(reason), comment, requested_date, policy, false, options)
|
209
195
|
end
|
210
196
|
|
211
|
-
def self.delete_subscription(subscription_id, current_user = nil, reason = nil, comment = nil,
|
212
|
-
|
197
|
+
def self.delete_subscription(subscription_id, current_user = nil, reason = nil, comment = nil, entitlement_policy = nil, billing_policy = nil, options = {})
|
213
198
|
entitlement = KillBillClient::Model::Subscription.new
|
214
199
|
entitlement.subscription_id = subscription_id
|
215
|
-
|
216
|
-
entitlement.cancel(extract_created_by(current_user), extract_reason_code(reason), comment, nil, policy, policy, true, options)
|
200
|
+
entitlement.cancel(extract_created_by(current_user), extract_reason_code(reason), comment, nil, entitlement_policy, billing_policy, true, options)
|
217
201
|
end
|
218
202
|
|
219
203
|
def self.reinstate_subscription(subscription_id, current_user = nil, reason = nil, comment = nil, options = {})
|
@@ -338,7 +322,7 @@ module Kaui
|
|
338
322
|
|
339
323
|
def self.pay_all_invoices(account_id, external = false, current_user = nil, reason = nil, comment = nil, options = {})
|
340
324
|
call_killbill :post,
|
341
|
-
"/1.0/kb/
|
325
|
+
"/1.0/kb/accounts/#{account_id}/payments?externalPayment=#{external}",
|
342
326
|
ActiveSupport::JSON.encode({:accountId => account_id}, :root => false),
|
343
327
|
build_audit_headers(current_user, reason, comment, options)
|
344
328
|
end
|
@@ -361,22 +345,20 @@ module Kaui
|
|
361
345
|
|
362
346
|
############## PAYMENT METHOD ##############
|
363
347
|
|
348
|
+
def self.get_payment_methods(offset, limit, options = {})
|
349
|
+
KillBillClient::Model::PaymentMethod.find_in_batches offset, limit, options
|
350
|
+
end
|
351
|
+
|
352
|
+
def self.search_payment_methods(search_key, offset, limit, options = {})
|
353
|
+
KillBillClient::Model::PaymentMethod.find_in_batches_by_search_key search_key, offset, limit, options
|
354
|
+
end
|
355
|
+
|
364
356
|
def self.delete_payment_method(payment_method_id, set_auto_pay_off = false, current_user = nil, reason = nil, comment = nil, options = {})
|
365
357
|
KillBillClient::Model::PaymentMethod.destroy payment_method_id, set_auto_pay_off, extract_created_by(current_user), extract_reason_code(reason), comment, options
|
366
358
|
end
|
367
359
|
|
368
360
|
def self.get_non_external_payment_methods(account_id, options = {})
|
369
|
-
|
370
|
-
end
|
371
|
-
|
372
|
-
def self.get_payment_methods(key, options = {})
|
373
|
-
if key =~ /[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}/
|
374
|
-
#looks like its account_id
|
375
|
-
KillBillClient::Model::PaymentMethod.find_all_by_account_id key, true, options
|
376
|
-
else
|
377
|
-
#any search key
|
378
|
-
KillBillClient::Model::PaymentMethod.find_all_by_search_key key, true, options
|
379
|
-
end
|
361
|
+
KillBillClient::Model::PaymentMethod.find_all_by_account_id(account_id, true, options).reject { |x| x.plugin_name == '__EXTERNAL_PAYMENT__' }
|
380
362
|
end
|
381
363
|
|
382
364
|
def self.get_payment_method(payment_method_id, options = {})
|
@@ -444,11 +426,16 @@ module Kaui
|
|
444
426
|
############## CREDIT ##############
|
445
427
|
|
446
428
|
def self.create_credit(credit, current_user = nil, reason = nil, comment = nil, options = {})
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
429
|
+
new_credit = KillBillClient::Model::Credit.new
|
430
|
+
new_credit.credit_amount = credit['credit_amount']
|
431
|
+
new_credit.invoice_id = credit['invoice_id']
|
432
|
+
new_credit.effective_date = credit['effective_date']
|
433
|
+
new_credit.account_id = credit['account_id']
|
434
|
+
|
435
|
+
new_credit.create(extract_created_by(current_user),
|
436
|
+
extract_reason_code(reason),
|
437
|
+
comment,
|
438
|
+
options)
|
452
439
|
end
|
453
440
|
|
454
441
|
############## TAG ##############
|
@@ -307,7 +307,7 @@
|
|
307
307
|
});
|
308
308
|
}
|
309
309
|
|
310
|
-
eventsOrder = ["START_ENTITLEMENT", "START_BILLING", "PAUSE_ENTITLEMENT", "PAUSE_BILLING", "RESUME_ENTITLEMENT", "RESUME_BILLING", "PHASE", "CHANGE",
|
310
|
+
eventsOrder = ["START_ENTITLEMENT", "START_BILLING", "PAUSE_ENTITLEMENT", "PAUSE_BILLING", "RESUME_ENTITLEMENT", "RESUME_BILLING", "PHASE", "CHANGE", "STOP_ENTITLEMENT", "STOP_BILLING", "INVOICE", "PAYMENT", "REFUND", "CHARGEBACK"];
|
311
311
|
|
312
312
|
jQuery.fn.dataTableExt.oSort['timeline-event-asc'] = function(e1,e2) {
|
313
313
|
var x = eventsOrder.indexOf(e1);
|
@@ -352,7 +352,7 @@
|
|
352
352
|
"iDisplayLength": 100,
|
353
353
|
"bRetrieve": true,
|
354
354
|
// Force a predictive order for event types, invoices and payments
|
355
|
-
"aaSorting": [[1, 'desc'], [4, '
|
355
|
+
"aaSorting": [[1, 'desc'], [4, 'asc'], [3, 'desc']],
|
356
356
|
"aoColumns": [
|
357
357
|
{ "sType": 'date' },
|
358
358
|
{ "sType": 'date' },
|
@@ -1,14 +1,29 @@
|
|
1
|
-
|
2
|
-
<
|
3
|
-
<
|
4
|
-
|
5
|
-
<
|
6
|
-
<
|
7
|
-
|
8
|
-
</
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
<table id="accounts-table" class="table table-condensed">
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th>Account ID</th>
|
5
|
+
<th>Name</th>
|
6
|
+
<th>External key</th>
|
7
|
+
<th>Currency</th>
|
8
|
+
<th>City</th>
|
9
|
+
<th>Country</th>
|
10
|
+
</tr>
|
11
|
+
</thead>
|
12
|
+
<tbody>
|
13
|
+
<tr>
|
14
|
+
<td colspan="1" class="dataTables_empty">Loading data from server</td>
|
15
|
+
</tr>
|
16
|
+
</tbody>
|
17
|
+
</table>
|
18
|
+
|
19
|
+
<%= javascript_tag do %>
|
20
|
+
$(document).ready(function() {
|
21
|
+
$('#accounts-table').dataTable({
|
22
|
+
"sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>",
|
23
|
+
"sPaginationType": "bootstrap",
|
24
|
+
"bProcessing": true,
|
25
|
+
"bServerSide": true,
|
26
|
+
"sAjaxSource": "<%= accounts_pagination_path :format => :json %>"
|
27
|
+
});
|
28
|
+
});
|
14
29
|
<% end %>
|
@@ -88,6 +88,14 @@
|
|
88
88
|
<%= select_tag :reason, options_for_select(Kaui::Chargeback::SAMPLE_REASON_CODES) %>
|
89
89
|
</div>
|
90
90
|
</div>
|
91
|
+
<div class="control-group">
|
92
|
+
<%= label_tag :cancel_all_subs, "Cancel account subscriptions?", :class => "control-label" %>
|
93
|
+
<div class="controls">
|
94
|
+
<label class="checkbox">
|
95
|
+
<%= check_box_tag :cancel_all_subs %>
|
96
|
+
</label>
|
97
|
+
</div>
|
98
|
+
</div>
|
91
99
|
<div class="control-group">
|
92
100
|
<%= label_tag :comment, "Comment", :class => "control-label" %>
|
93
101
|
<div class="controls">
|
@@ -1,15 +1,28 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
<
|
5
|
-
|
1
|
+
<table id="paymentMethods-table" class="table table-condensed">
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th>Account ID</th>
|
5
|
+
<th>External ID</th>
|
6
|
+
<th>Type</th>
|
7
|
+
<th>CC name</th>
|
8
|
+
<th>CC last 4</th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<tbody>
|
12
|
+
<tr>
|
13
|
+
<td colspan="1" class="dataTables_empty">Loading data from server</td>
|
14
|
+
</tr>
|
15
|
+
</tbody>
|
16
|
+
</table>
|
6
17
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
<%= javascript_tag do %>
|
19
|
+
$(document).ready(function() {
|
20
|
+
$('#paymentMethods-table').dataTable({
|
21
|
+
"sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>",
|
22
|
+
"sPaginationType": "bootstrap",
|
23
|
+
"bProcessing": true,
|
24
|
+
"bServerSide": true,
|
25
|
+
"sAjaxSource": "<%= payment_methods_pagination_path :format => :json %>"
|
26
|
+
});
|
27
|
+
});
|
15
28
|
<% end %>
|
@@ -21,15 +21,15 @@
|
|
21
21
|
<td><%= format_date(sub.start_date, account.timezone).html_safe if sub.start_date.present? %></td>
|
22
22
|
<td><%= format_date(sub.charged_through_date, account.timezone).html_safe if sub.charged_through_date.present? %></td>
|
23
23
|
<td>
|
24
|
-
<% if sub.
|
25
|
-
<% if Time.parse(sub.
|
24
|
+
<% if sub.cancelled_date.present? && !sub.cancelled_date.nil? %>
|
25
|
+
<% if Time.parse(sub.cancelled_date) > Time.now %> <%= "Pending cancellation on " %> <% else %> <%= "Canceled on " %> <% end %> <%= format_date(sub.cancelled_date, account.timezone).html_safe %>
|
26
26
|
<% end %>
|
27
27
|
</td>
|
28
28
|
<td>
|
29
29
|
<nobr>
|
30
|
-
<% if sub.
|
30
|
+
<% if sub.cancelled_date.present? && Time.parse(sub.cancelled_date) > Time.now %>
|
31
31
|
<%= link_to "Reinstate", kaui_engine.reinstate_subscription_path(:id => sub.subscription_id), :method => :put, :class => "btn btn-mini" %>
|
32
|
-
<% elsif !sub.
|
32
|
+
<% elsif !sub.cancelled_date.present? %>
|
33
33
|
<%= link_to "Change", kaui_engine.edit_subscription_path(sub.subscription_id), :class => "btn btn-mini" %>
|
34
34
|
<div class="btn-group">
|
35
35
|
<a class="btn btn-mini dropdown-toggle" data-toggle="dropdown" href="#">
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% @page_title = "Edit Subscription" %>
|
2
|
-
<%= form_for(@subscription, :url => subscription_path(@subscription.subscription_id), :html => { :method => :put, :class => "form-horizontal" }) do |f| %>
|
2
|
+
<%= form_for(@subscription, :as => :subscription, :url => subscription_path(@subscription.subscription_id), :html => { :method => :put, :class => "form-horizontal" }) do |f| %>
|
3
3
|
<%= f.hidden_field :subscription_id %>
|
4
4
|
<%= f.hidden_field :price_list %>
|
5
5
|
<div class="control-group">
|
data/config/routes.rb
CHANGED
@@ -8,6 +8,9 @@ Kaui::Engine.routes.draw do
|
|
8
8
|
|
9
9
|
root :to => "home#index"
|
10
10
|
|
11
|
+
scope "/accounts" do
|
12
|
+
match "/pagination" => "accounts#pagination", :via => :get, :as => "accounts_pagination"
|
13
|
+
end
|
11
14
|
resources :accounts, :only => [ :index, :show ] do
|
12
15
|
member do
|
13
16
|
get :payment_methods
|
@@ -42,6 +45,9 @@ Kaui::Engine.routes.draw do
|
|
42
45
|
|
43
46
|
resources :payments, :only => [ :create, :new, :index, :show ]
|
44
47
|
|
48
|
+
scope "/payment_methods" do
|
49
|
+
match "/pagination" => "payment_methods#pagination", :via => :get, :as => "payment_methods_pagination"
|
50
|
+
end
|
45
51
|
resources :payment_methods, :only => [ :index, :show, :destroy ]
|
46
52
|
|
47
53
|
resources :refunds, :only => [ :index, :show, :create, :new ]
|
data/kaui.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_dependency 'rest-client', '~> 1.6.7'
|
28
28
|
s.add_dependency 'money-rails', '~> 0.8.1'
|
29
29
|
s.add_dependency 'd3_rails', '~> 3.2.8'
|
30
|
-
s.add_dependency 'killbill-client', '~> 0.
|
30
|
+
s.add_dependency 'killbill-client', '~> 0.5.1'
|
31
31
|
s.add_dependency 'devise', '~> 3.0.2'
|
32
32
|
s.add_dependency 'cancan', '~> 1.6.10'
|
33
33
|
|
data/lib/kaui/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kaui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.6.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Killbill core team
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-10-26 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rails
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,7 +27,6 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: jquery-rails
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ~>
|
36
32
|
- !ruby/object:Gem::Version
|
@@ -38,7 +34,6 @@ dependencies:
|
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ~>
|
44
39
|
- !ruby/object:Gem::Version
|
@@ -46,7 +41,6 @@ dependencies:
|
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: rest-client
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ~>
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,7 +48,6 @@ dependencies:
|
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ~>
|
60
53
|
- !ruby/object:Gem::Version
|
@@ -62,7 +55,6 @@ dependencies:
|
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: money-rails
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
59
|
- - ~>
|
68
60
|
- !ruby/object:Gem::Version
|
@@ -70,7 +62,6 @@ dependencies:
|
|
70
62
|
type: :runtime
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
66
|
- - ~>
|
76
67
|
- !ruby/object:Gem::Version
|
@@ -78,7 +69,6 @@ dependencies:
|
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: d3_rails
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
73
|
- - ~>
|
84
74
|
- !ruby/object:Gem::Version
|
@@ -86,7 +76,6 @@ dependencies:
|
|
86
76
|
type: :runtime
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
80
|
- - ~>
|
92
81
|
- !ruby/object:Gem::Version
|
@@ -94,23 +83,20 @@ dependencies:
|
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: killbill-client
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
87
|
- - ~>
|
100
88
|
- !ruby/object:Gem::Version
|
101
|
-
version: 0.
|
89
|
+
version: 0.5.1
|
102
90
|
type: :runtime
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
94
|
- - ~>
|
108
95
|
- !ruby/object:Gem::Version
|
109
|
-
version: 0.
|
96
|
+
version: 0.5.1
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: devise
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
101
|
- - ~>
|
116
102
|
- !ruby/object:Gem::Version
|
@@ -118,7 +104,6 @@ dependencies:
|
|
118
104
|
type: :runtime
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
108
|
- - ~>
|
124
109
|
- !ruby/object:Gem::Version
|
@@ -126,7 +111,6 @@ dependencies:
|
|
126
111
|
- !ruby/object:Gem::Dependency
|
127
112
|
name: cancan
|
128
113
|
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
114
|
requirements:
|
131
115
|
- - ~>
|
132
116
|
- !ruby/object:Gem::Version
|
@@ -134,7 +118,6 @@ dependencies:
|
|
134
118
|
type: :runtime
|
135
119
|
prerelease: false
|
136
120
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
121
|
requirements:
|
139
122
|
- - ~>
|
140
123
|
- !ruby/object:Gem::Version
|
@@ -142,33 +125,29 @@ dependencies:
|
|
142
125
|
- !ruby/object:Gem::Dependency
|
143
126
|
name: sqlite3
|
144
127
|
requirement: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
128
|
requirements:
|
147
|
-
- -
|
129
|
+
- - '>='
|
148
130
|
- !ruby/object:Gem::Version
|
149
131
|
version: '0'
|
150
132
|
type: :development
|
151
133
|
prerelease: false
|
152
134
|
version_requirements: !ruby/object:Gem::Requirement
|
153
|
-
none: false
|
154
135
|
requirements:
|
155
|
-
- -
|
136
|
+
- - '>='
|
156
137
|
- !ruby/object:Gem::Version
|
157
138
|
version: '0'
|
158
139
|
- !ruby/object:Gem::Dependency
|
159
140
|
name: mysql2
|
160
141
|
requirement: !ruby/object:Gem::Requirement
|
161
|
-
none: false
|
162
142
|
requirements:
|
163
|
-
- -
|
143
|
+
- - '>='
|
164
144
|
- !ruby/object:Gem::Version
|
165
145
|
version: '0'
|
166
146
|
type: :development
|
167
147
|
prerelease: false
|
168
148
|
version_requirements: !ruby/object:Gem::Requirement
|
169
|
-
none: false
|
170
149
|
requirements:
|
171
|
-
- -
|
150
|
+
- - '>='
|
172
151
|
- !ruby/object:Gem::Version
|
173
152
|
version: '0'
|
174
153
|
description: Rails UI plugin for Killbill administration.
|
@@ -417,30 +396,26 @@ files:
|
|
417
396
|
homepage: http://www.killbilling.org
|
418
397
|
licenses:
|
419
398
|
- Apache License (2.0)
|
399
|
+
metadata: {}
|
420
400
|
post_install_message:
|
421
401
|
rdoc_options: []
|
422
402
|
require_paths:
|
423
403
|
- lib
|
424
404
|
required_ruby_version: !ruby/object:Gem::Requirement
|
425
|
-
none: false
|
426
405
|
requirements:
|
427
|
-
- -
|
406
|
+
- - '>='
|
428
407
|
- !ruby/object:Gem::Version
|
429
408
|
version: 1.8.7
|
430
409
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
431
|
-
none: false
|
432
410
|
requirements:
|
433
|
-
- -
|
411
|
+
- - '>='
|
434
412
|
- !ruby/object:Gem::Version
|
435
413
|
version: '0'
|
436
|
-
segments:
|
437
|
-
- 0
|
438
|
-
hash: -2070916750925486573
|
439
414
|
requirements: []
|
440
415
|
rubyforge_project:
|
441
|
-
rubygems_version:
|
416
|
+
rubygems_version: 2.0.3
|
442
417
|
signing_key:
|
443
|
-
specification_version:
|
418
|
+
specification_version: 4
|
444
419
|
summary: Killbill Admin UI plugin
|
445
420
|
test_files:
|
446
421
|
- test/dummy/README.rdoc
|