kaui 0.15.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/app/assets/stylesheets/kaui/common.less +0 -6
  4. data/app/assets/stylesheets/kaui/datatable.less +14 -0
  5. data/app/assets/stylesheets/kaui/home.less +4 -0
  6. data/app/controllers/kaui/accounts_controller.rb +37 -0
  7. data/app/controllers/kaui/admin_allowed_users_controller.rb +2 -2
  8. data/app/controllers/kaui/admin_controller.rb +27 -0
  9. data/app/controllers/kaui/admin_tenants_controller.rb +8 -2
  10. data/app/controllers/kaui/engine_controller.rb +2 -2
  11. data/app/controllers/kaui/engine_controller_util.rb +1 -1
  12. data/app/controllers/kaui/home_controller.rb +3 -1
  13. data/app/controllers/kaui/invoices_controller.rb +10 -0
  14. data/app/controllers/kaui/payments_controller.rb +31 -7
  15. data/app/controllers/kaui/queues_controller.rb +11 -0
  16. data/app/controllers/kaui/subscriptions_controller.rb +20 -2
  17. data/app/controllers/kaui/tags_controller.rb +11 -0
  18. data/app/controllers/kaui/transactions_controller.rb +27 -4
  19. data/app/helpers/kaui/account_helper.rb +1 -1
  20. data/app/helpers/kaui/application_helper.rb +5 -0
  21. data/app/helpers/kaui/date_helper.rb +5 -1
  22. data/app/helpers/kaui/payment_helper.rb +9 -0
  23. data/app/models/kaui/admin.rb +75 -0
  24. data/app/models/kaui/invoice_payment.rb +26 -9
  25. data/app/models/kaui/payment.rb +2 -0
  26. data/app/models/kaui/payment_method.rb +18 -5
  27. data/app/models/kaui/transaction.rb +8 -0
  28. data/app/models/kaui/user.rb +4 -0
  29. data/app/views/kaui/accounts/_account_info.html.erb +23 -2
  30. data/app/views/kaui/accounts/_billing_info.html.erb +21 -0
  31. data/app/views/kaui/accounts/_form.html.erb +14 -8
  32. data/app/views/kaui/accounts/index.html.erb +5 -2
  33. data/app/views/kaui/admin/index.html.erb +39 -0
  34. data/app/views/kaui/admin/index.js.erb +3 -0
  35. data/app/views/kaui/admin_allowed_users/show.html.erb +2 -2
  36. data/app/views/kaui/admin_tenants/_tenant_details.html.erb +15 -0
  37. data/app/views/kaui/admin_tenants/_useful_links.html.erb +18 -0
  38. data/app/views/kaui/admin_tenants/new_catalog.html.erb +0 -1
  39. data/app/views/kaui/admin_tenants/new_overdue_config.html.erb +0 -1
  40. data/app/views/kaui/admin_tenants/show.html.erb +42 -12
  41. data/app/views/kaui/home/index.html.erb +8 -1
  42. data/app/views/kaui/invoices/_invoice_table.html.erb +1 -1
  43. data/app/views/kaui/invoices/index.html.erb +13 -3
  44. data/app/views/kaui/invoices/show.html.erb +11 -1
  45. data/app/views/kaui/layouts/kaui_account_navbar.html.erb +4 -0
  46. data/app/views/kaui/layouts/kaui_navbar.html.erb +19 -12
  47. data/app/views/kaui/payments/_payment_table.html.erb +60 -50
  48. data/app/views/kaui/payments/index.html.erb +13 -3
  49. data/app/views/kaui/payments/show.html.erb +6 -0
  50. data/app/views/kaui/queues/index.html.erb +124 -0
  51. data/app/views/kaui/subscriptions/_edit_form.html.erb +4 -4
  52. data/app/views/kaui/subscriptions/_form.html.erb +3 -3
  53. data/app/views/kaui/subscriptions/_subscriptions_table.html.erb +25 -22
  54. data/app/views/kaui/subscriptions/edit_bcd.erb +29 -0
  55. data/app/views/kaui/tags/index.html.erb +7 -1
  56. data/app/views/kaui/transactions/_form.html.erb +16 -6
  57. data/config/routes.rb +23 -4
  58. data/kaui.gemspec +1 -1
  59. data/lib/kaui/version.rb +1 -1
  60. data/test/fixtures/catalog-v1.xml +0 -1
  61. metadata +161 -151
@@ -3,7 +3,7 @@ module Kaui
3
3
 
4
4
  def pretty_account_identifier
5
5
  return nil if @account.nil?
6
- @account.name.presence || @account.email.presence || @account.external_key
6
+ @account.name.presence || @account.email.presence || truncate_uuid(@account.external_key)
7
7
  end
8
8
  end
9
9
  end
@@ -4,5 +4,10 @@ module Kaui
4
4
  def tenant_selected?
5
5
  session[:kb_tenant_id].present?
6
6
  end
7
+
8
+ def truncate_class_name(klass, with_abbr = false)
9
+ splitted = klass.split('.')
10
+ with_abbr ? splitted.each_with_index.map { |k, idx| idx == splitted.size - 1 ? k : k[0]+'.' }.join : splitted[-1]
11
+ end
7
12
  end
8
13
  end
@@ -15,5 +15,9 @@ module Kaui
15
15
  parsed_date = DateTime.parse(date.to_s).in_time_zone(timezone)
16
16
  parsed_date.to_s(:date_only)
17
17
  end
18
+
19
+ def truncate_millis(date_s)
20
+ DateTime.parse(date_s).strftime('%FT%T')
21
+ end
18
22
  end
19
- end
23
+ end
@@ -0,0 +1,9 @@
1
+ module Kaui
2
+ module PaymentHelper
3
+
4
+ def transaction_statuses
5
+ Kaui::Payment::TRANSACTION_STATUSES
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,75 @@
1
+ class Kaui::Admin < KillBillClient::Model::Resource
2
+
3
+ KILLBILL_API_ADMIN_PREFIX = "#{KILLBILL_API_PREFIX}/admin"
4
+ KILLBILL_API_CLOCK_PREFIX = "#{KILLBILL_API_PREFIX}/test/clock"
5
+ KILLBILL_API_QUEUES_PREFIX = "#{KILLBILL_API_ADMIN_PREFIX}/queues"
6
+
7
+ class << self
8
+
9
+ def get_queues_entries(account_id, options = {})
10
+ res = KillBillClient::API.get KILLBILL_API_QUEUES_PREFIX,
11
+ {
12
+ :accountId => account_id,
13
+ :withHistory => options[:withHistory],
14
+ :minDate => options[:minDate]
15
+ },
16
+ options
17
+ JSON.parse res.body
18
+ end
19
+
20
+ def fix_transaction_state(payment_id, transaction_id, transaction_status, user = nil, reason = nil, comment = nil, options = {})
21
+ res = KillBillClient::API.put "#{KILLBILL_API_ADMIN_PREFIX}/payments/#{payment_id}/transactions/#{transaction_id}",
22
+ {:transactionStatus => transaction_status}.to_json,
23
+ {},
24
+ {
25
+ :user => user,
26
+ :reason => reason,
27
+ :comment => comment,
28
+ }.merge(options)
29
+ end
30
+
31
+ def get_clock(time_zone, options)
32
+ params = {}
33
+ params[:timeZone] = time_zone unless time_zone.nil?
34
+
35
+ res = KillBillClient::API.get KILLBILL_API_CLOCK_PREFIX,
36
+ params,
37
+ options
38
+ JSON.parse res.body
39
+ end
40
+
41
+ def set_clock(requested_date, time_zone, options)
42
+ params = {}
43
+ params[:requestedDate] = requested_date unless requested_date.nil?
44
+ params[:timeZone] = time_zone unless time_zone.nil?
45
+
46
+ # The default 5s is not always enough
47
+ params[:timeoutSec] ||= 10
48
+
49
+ res = KillBillClient::API.post KILLBILL_API_CLOCK_PREFIX,
50
+ {},
51
+ params,
52
+ {}.merge(options)
53
+ JSON.parse res.body
54
+ end
55
+
56
+ def increment_kb_clock(days, weeks, months, years, time_zone, options)
57
+ params = {}
58
+ params[:days] = days unless days.nil?
59
+ params[:weeks] = weeks unless weeks.nil?
60
+ params[:months] = months unless months.nil?
61
+ params[:years] = years unless years.nil?
62
+ params[:timeZone] = time_zone unless time_zone.nil?
63
+
64
+ # The default 5s is not always enough
65
+ params[:timeoutSec] ||= 10
66
+
67
+ res = KillBillClient::API.put KILLBILL_API_CLOCK_PREFIX,
68
+ {},
69
+ params,
70
+ {}.merge(options)
71
+
72
+ JSON.parse res.body
73
+ end
74
+ end
75
+ end
@@ -7,6 +7,14 @@ class Kaui::InvoicePayment < KillBillClient::Model::InvoicePayment
7
7
 
8
8
  class << self
9
9
 
10
+ def find_safely_by_id(id, options = {})
11
+ Kaui::InvoicePayment.find_by_id(id, true, true, options)
12
+ rescue => e
13
+ # Maybe the plugin is not registered or the plugin threw an exception
14
+ Rails.logger.warn(e)
15
+ Kaui::InvoicePayment.find_by_id(id, false, true, options)
16
+ end
17
+
10
18
  def build_from_raw_payment(raw_payment)
11
19
 
12
20
  return nil if raw_payment.nil?
@@ -39,16 +47,25 @@ class Kaui::InvoicePayment < KillBillClient::Model::InvoicePayment
39
47
 
40
48
  # For each payment transaction, compute next_retry date by joining with payment attempts
41
49
  def build_transactions_next_retry_date!
42
- (transactions || []).each do |transaction|
43
- # Filter attempts matching that transaction and SCHEDULED for retry
44
- transaction.next_retry_date = (payment_attempts || []).select do |attempt|
45
- ((attempt.transaction_id && attempt.transaction_id == transaction.transaction_id) ||
46
- (attempt.transaction_external_key && attempt.transaction_external_key == transaction.transaction_external_key)) &&
47
- attempt.state_name == 'SCHEDULED'
48
- end.map do |attempt|
49
- attempt.effective_date
50
- end.first
50
+
51
+ # Filter scheduled attempts: We could have several in parallel when multiple independent transactions occur at the same time
52
+ # (They would have different transaction_external_key)
53
+ scheduled_attempts = (payment_attempts || []).select do |a|
54
+ a.state_name == 'SCHEDULED'
55
+ end
56
+
57
+ # Look for latest transaction associated with each such scheduled attempt and set retry date accordingly
58
+ scheduled_attempts.each do |a|
59
+
60
+ last_transaction_for_attempt = (transactions || []).select do |t|
61
+ t.transaction_external_key == a.transaction_external_key
62
+ end.sort_by do |t|
63
+ t.effective_date
64
+ end.last
65
+
66
+ last_transaction_for_attempt.next_retry_date = a.effective_date if last_transaction_for_attempt
51
67
  end
68
+
52
69
  end
53
70
 
54
71
  end
@@ -4,6 +4,8 @@ class Kaui::Payment < KillBillClient::Model::Payment
4
4
 
5
5
  attr_accessor :payment_date, :target_invoice_id
6
6
 
7
+ TRANSACTION_STATUSES = %w(SUCCESS PENDING PAYMENT_FAILURE PLUGIN_FAILURE UNKNOWN)
8
+
7
9
  SAMPLE_REASON_CODES = ['600 - Alt payment method',
8
10
  '699 - OTHER']
9
11
 
@@ -8,13 +8,26 @@ class Kaui::PaymentMethod < KillBillClient::Model::PaymentMethod
8
8
  end
9
9
  end
10
10
 
11
+ def self.find_safely_by_id(id, options = {})
12
+ Kaui::PaymentMethod.find_by_id(id, true, options)
13
+ rescue => e
14
+ # Maybe the plugin is not registered or the plugin threw an exception
15
+ Rails.logger.warn(e)
16
+ Kaui::PaymentMethod.find_by_id(id, false, options) rescue nil # deleted pm?
17
+ end
18
+
11
19
  def self.find_all_safely_by_account_id(account_id, options = {})
12
- begin
13
- Kaui::PaymentMethod.find_all_by_account_id(account_id, true, options)
14
- rescue KillBillClient::API::BadRequest
15
- # Maybe the plugin(s) are not registered?
16
- Kaui::PaymentMethod.find_all_by_account_id(account_id, false, options)
20
+ pms = Kaui::PaymentMethod.find_all_by_account_id(account_id, false, options)
21
+
22
+ pms.each_with_index do |pm, i|
23
+ begin
24
+ pms[i] = Kaui::PaymentMethod.find_by_id(pm.payment_method_id, true, options)
25
+ rescue => e
26
+ # Maybe the plugin is not registered or the plugin threw an exception
27
+ Rails.logger.warn(e)
28
+ end
17
29
  end
30
+ pms
18
31
  end
19
32
 
20
33
  def self.find_non_external_by_account_id(account_id, with_plugin_info = false, options = {})
@@ -2,6 +2,14 @@ class Kaui::Transaction < KillBillClient::Model::Transaction
2
2
 
3
3
  attr_accessor :next_retry_date
4
4
 
5
+ def self.build_from_raw_transaction(raw_transaction)
6
+ result = Kaui::Transaction.new
7
+ KillBillClient::Model::PaymentTransactionAttributes.instance_variable_get('@json_attributes').each do |attr|
8
+ result.send("#{attr}=", raw_transaction.send(attr))
9
+ end
10
+ result
11
+ end
12
+
5
13
  def create(account_id = nil, payment_method_id = nil, user = nil, reason = nil, comment = nil, options = {})
6
14
  if transaction_type == 'AUTHORIZE'
7
15
  auth(account_id, payment_method_id, user, reason, comment, options)
@@ -35,6 +35,10 @@ module Kaui
35
35
  end
36
36
  end
37
37
 
38
+ def root?
39
+ Kaui.root_username == kb_username
40
+ end
41
+
38
42
  private
39
43
 
40
44
  def self.do_find_permissions(options = {})
@@ -10,6 +10,15 @@
10
10
  <% end %>
11
11
  </h1>
12
12
 
13
+ <% unless @tags.find { |tag| tag.tag_definition_name == '__PARK__' }.nil? %>
14
+ <div class="alert alert-danger">
15
+ This account is parked, meaning the system detected inconsistent state which could lead to mis-billing. For safety, no more invoices will be generated.
16
+ <% if can? :trigger, Kaui::Invoice %>
17
+ Once the data is fixed, you can unpark it by manually <%= link_to 'triggering an invoice run', kaui_engine.trigger_invoice_path(params), :method => :post %>.
18
+ <% end %>
19
+ </div>
20
+ <% end %>
21
+
13
22
  <div class="info-wrapper">
14
23
 
15
24
  <div class="tag-bar tag-bar-breathe">
@@ -49,8 +58,20 @@
49
58
  <td><%= @account.currency %></td>
50
59
  </tr>
51
60
  <tr>
52
- <th>Timezone</th>
53
- <td><%= @account.time_zone %></td>
61
+ <th>Timezone</th>
62
+ <td><%= @account.time_zone %></td>
63
+ </tr>
64
+ <tr>
65
+ <th>Locale</th>
66
+ <td><%= @account.locale %></td>
67
+ </tr>
68
+ <tr>
69
+ <th>Notes</th>
70
+ <% if @account.notes %>
71
+ <td><textarea rows="3" class="form-control" readonly="true"><%= @account.notes %></textarea></td>
72
+ <% else %>
73
+ <td>N/A</td>
74
+ <% end %>
54
75
  </tr>
55
76
  </table>
56
77
  </div>
@@ -95,6 +95,27 @@
95
95
  </td>
96
96
  </tr>
97
97
  </table>
98
+
99
+ <% if can? :trigger, Kaui::Invoice %>
100
+ <div style="padding-bottom: 50px;">
101
+ <%= form_tag kaui_engine.trigger_invoice_path(params), :method => :post do %>
102
+ <div class="form-group">
103
+ <%= label_tag :target_date, 'Trigger invoice generation', :class => 'col-sm-6 control-label', :style => 'padding-left: 0;' %>
104
+ <div class="col-sm-3">
105
+ <input class="form-control" name="target_date" type="text" data-provide="datepicker" data-date-format="yyyy-mm-dd" data-date-today-highlight="true">
106
+ </div>
107
+ <div style="width: 14.5%; float: left; padding: 0;">
108
+ <%= label_tag :dry_run do %>
109
+ <%= check_box_tag :dry_run, '1', true %>&nbsp;<small>Dry-run</small>
110
+ <% end %>
111
+ </div>
112
+ <div class="col-xs-1" style="padding: 0;">
113
+ <%= button_tag '<i class="fa fa-magic"></i>'.html_safe, :class => 'btn btn-xs' %>
114
+ </div>
115
+ </div>
116
+ <% end %>
117
+ </div>
118
+ <% end %>
98
119
  </div>
99
120
  </div>
100
121
 
@@ -46,6 +46,12 @@
46
46
  </div>
47
47
  </div>
48
48
  <% end %>
49
+ <div class="form-group">
50
+ <%= f.label :locale, 'Locale', :class => 'col-sm-3 control-label' %>
51
+ <div class="col-sm-9">
52
+ <%= f.text_field :locale, :class => 'form-control' %>
53
+ </div>
54
+ </div>
49
55
  <div class="form-group">
50
56
  <%= f.label :address1, 'Address line 1', :class => 'col-sm-3 control-label' %>
51
57
  <div class="col-sm-9">
@@ -89,16 +95,16 @@
89
95
  </div>
90
96
  </div>
91
97
  <div class="form-group">
92
- <%= f.label :locale, 'Locale', :class => 'col-sm-3 control-label' %>
93
- <div class="col-sm-9">
94
- <%= f.text_field :locale, :class => 'form-control' %>
95
- </div>
98
+ <%= f.label :phone, 'Phone', :class => 'col-sm-3 control-label' %>
99
+ <div class="col-sm-9">
100
+ <%= f.text_field :phone, :class => 'form-control' %>
101
+ </div>
96
102
  </div>
97
103
  <div class="form-group">
98
- <%= f.label :phone, 'Phone', :class => 'col-sm-3 control-label' %>
99
- <div class="col-sm-9">
100
- <%= f.text_field :phone, :class => 'form-control' %>
101
- </div>
104
+ <%= f.label :notes, 'Notes', :class => 'col-sm-3 control-label' %>
105
+ <div class="col-sm-9">
106
+ <%= f.text_field :notes, :class => 'form-control' %>
107
+ </div>
102
108
  </div>
103
109
  <% unless @account.persisted? %>
104
110
  <div class="form-group">
@@ -35,8 +35,11 @@ $(document).ready(function() {
35
35
  $('#accounts-table').dataTable({
36
36
  "dom": "<'row'r>t<'row'<'col-md-6'i><'col-md-6'p>>",
37
37
  "pagingType": "full_numbers",
38
- "pageLength": 50,
39
- "order": [[ 0, "asc" ]],
38
+ "pageLength": <%= @limit %>,
39
+ "displayStart": <%= @offset %>,
40
+ <% unless @ordering.blank? %>
41
+ "order": [[ 0, "<%= @ordering %>" ]],
42
+ <% end %>
40
43
  "processing": true,
41
44
  "serverSide": true,
42
45
  "search": {"search": "<%= @search_query %>"},
@@ -0,0 +1,39 @@
1
+ <div class="column-block">
2
+
3
+ <h1>Clock</h1>
4
+
5
+ <ul>
6
+ <li>Current date/time: <span id="kb_clock"><%= @clock['currentUtcTime'] %></span></li>
7
+ </ul>
8
+
9
+ <div>
10
+ <%= form_tag kaui_engine.admin_set_clock_path(params), :method => :put, :class => 'form-horizontal' do %>
11
+ <div class="form-group">
12
+ <%= label_tag :new_date, 'Set new date', :class => 'col-sm-2 control-label' %>
13
+ <div class="col-sm-2">
14
+ <input class="form-control" name="new_date" type="text" data-provide="datepicker" data-date-format="yyyy-mm-dd" data-date-today-highlight="true" value="<%= @clock['localDate'] %>">
15
+ </div>
16
+ </div>
17
+ <div class="form-group">
18
+ <div class="col-sm-offset-2 col-sm-10">
19
+ <%= submit_tag 'Submit', :class => 'btn btn-default' %>
20
+ <%= button_tag 'Reset', :class => 'btn btn-danger' %>
21
+ </div>
22
+ </div>
23
+ <% end %>
24
+ </div>
25
+ </div>
26
+
27
+ <%= javascript_tag do %>
28
+ $(document).ready(function() {
29
+ scheduleRefresh();
30
+ });
31
+
32
+ function scheduleRefresh() {
33
+ setTimeout(refreshClock, 1000);
34
+ }
35
+
36
+ function refreshClock() {
37
+ $.ajax({url: "<%= admin_path(:format => :js) %>"});
38
+ }
39
+ <% end %>
@@ -0,0 +1,3 @@
1
+ $('#kb_clock').html("<%= @clock['currentUtcTime'] %>");
2
+
3
+ scheduleRefresh();
@@ -22,14 +22,14 @@
22
22
  <% @tenants.each do |tenant| %>
23
23
  <div class="checkbox">
24
24
  <label>
25
- <%= check_box_tag "tenant_#{tenant.id}", tenant.id, @allowed_user.kaui_tenants.map(&:id).include?(tenant.id), :disabled => Kaui.root_username != current_user.kb_username %>
25
+ <%= check_box_tag "tenant_#{tenant.id}", tenant.id, @allowed_user.kaui_tenants.map(&:id).include?(tenant.id), :disabled => !current_user.root? %>
26
26
  <span><%= tenant.name || tenant.api_key %></span>
27
27
  </label>
28
28
  </div>
29
29
  <% end %>
30
30
  </div>
31
31
  </div>
32
- <% unless Kaui.root_username != current_user.kb_username %>
32
+ <% unless !current_user.root? %>
33
33
  <div class="form-group">
34
34
  <div class="col-sm-offset-2 col-sm-10">
35
35
  <%= f.submit 'Save', :class => 'btn btn-default' %>
@@ -0,0 +1,15 @@
1
+ <div class="col-md-6">
2
+
3
+ <div class="column-block">
4
+
5
+ <h1>Tenant details</h1>
6
+
7
+ <b>Name:</b> <%= @tenant.name %>
8
+ <br/>
9
+ <b>Tenant ID:</b> <%= @tenant.kb_tenant_id %>
10
+ <br/>
11
+ <b>API Key:</b> <%= @tenant.api_key %>
12
+
13
+ </div>
14
+
15
+ </div>