kaui 3.0.3 → 3.0.5

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/kaui/account_timelines_controller.rb +117 -0
  3. data/app/controllers/kaui/accounts_controller.rb +50 -7
  4. data/app/controllers/kaui/audit_logs_controller.rb +37 -0
  5. data/app/controllers/kaui/bundles_controller.rb +5 -1
  6. data/app/controllers/kaui/engine_controller.rb +3 -28
  7. data/app/controllers/kaui/engine_controller_util.rb +8 -2
  8. data/app/controllers/kaui/invoices_controller.rb +54 -29
  9. data/app/controllers/kaui/payments_controller.rb +69 -9
  10. data/app/controllers/kaui/sessions_controller.rb +7 -0
  11. data/app/helpers/kaui/exception_helper.rb +25 -0
  12. data/app/helpers/kaui/subscription_helper.rb +5 -1
  13. data/app/models/kaui/account.rb +9 -0
  14. data/app/models/kaui/invoice.rb +2 -0
  15. data/app/models/kaui/payment.rb +7 -0
  16. data/app/views/kaui/account_timelines/_multi_functions_bar.html.erb +155 -0
  17. data/app/views/kaui/account_timelines/show.html.erb +2 -0
  18. data/app/views/kaui/accounts/_account_info.html.erb +7 -0
  19. data/app/views/kaui/accounts/_multi_functions_bar.html.erb +329 -0
  20. data/app/views/kaui/accounts/index.html.erb +32 -18
  21. data/app/views/kaui/audit_logs/_multi_functions_bar.html.erb +189 -0
  22. data/app/views/kaui/audit_logs/index.html.erb +8 -0
  23. data/app/views/kaui/bundles/index.html.erb +34 -0
  24. data/app/views/kaui/errors/500.html.erb +29 -0
  25. data/app/views/kaui/invoices/_multi_functions_bar.html.erb +322 -0
  26. data/app/views/kaui/invoices/index.html.erb +49 -24
  27. data/app/views/kaui/payments/_multi_functions_bar.html.erb +323 -0
  28. data/app/views/kaui/payments/index.html.erb +73 -30
  29. data/config/locales/en.yml +3 -0
  30. data/config/routes.rb +7 -0
  31. data/lib/kaui/error_handler.rb +37 -0
  32. data/lib/kaui/version.rb +1 -1
  33. data/lib/kaui.rb +117 -30
  34. metadata +13 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fdb45a75d2f3a57307ffe426a864911262563d623f25cccefd3941de52655e36
4
- data.tar.gz: f45cbd12e90f63dfb544743381af6c4a2dbeab58fe0671334f02198bdeb97323
3
+ metadata.gz: f1d09c53f971465792983fa62e85842cf0f7807e429793bcfaf298129fc30720
4
+ data.tar.gz: 4536845ab8261e1e16ef4d9a8caba638e62fd4b02090fe0142430fb4d988e8ed
5
5
  SHA512:
6
- metadata.gz: 065274ae77055af9c3a54b7938f8c8f0d09775b5d7a7b4e953c990790ad7e4af247096b287f308062e53f09b13d16eda146ccd893c762baa3dc7ab644f8a3c01
7
- data.tar.gz: 15cd32d52a680d624be8bf85f3db439f1afc78ad5d7308054fecf7aad66d130f8a5bd324ec93ba7fd140399be84f4eec6015e1c9a054f55f368f8c4202ecebfb
6
+ metadata.gz: a3f5018cfde24d5a5a53634a3b4098bb45cd439e0bcad1497163bb928737e6b628b6af430f4e3ff4ba792ed0e72c25c57f7a34f20a49480480383c35e4ddf741
7
+ data.tar.gz: e4079ed0b2ec629b9fb1ea6fbbc4d617515ec78e2cc75cc4b2742578164c14e8b2d344ebeebba5e3ca83a7a100cf844f0d65cef93d0d770d7743c94444bbb8a9
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'csv'
4
+
3
5
  module Kaui
4
6
  class AccountTimelinesController < Kaui::EngineController
5
7
  def show
@@ -30,8 +32,123 @@ module Kaui
30
32
  @selected_bundle = params.key?(:external_key) ? @bundle_names[params[:external_key]] : nil
31
33
  end
32
34
 
35
+ def download
36
+ timeline = Kaui::AccountTimeline.find_by_account_id(params.require(:account_id), 'FULL', options_for_klient)
37
+ start_date = begin
38
+ Date.parse(params[:startDate])
39
+ rescue StandardError
40
+ nil
41
+ end
42
+ end_date = begin
43
+ Date.parse(params[:endDate])
44
+ rescue StandardError
45
+ nil
46
+ end
47
+
48
+ event_type = params[:eventType]
49
+ @account = timeline.account
50
+ @bundles = timeline.bundles
51
+ @invoices = timeline.invoices
52
+ @payments = timeline.payments
53
+ extract_invoices_by_id(@invoices)
54
+
55
+ # Lookup all bundle names
56
+ @bundle_names = {}
57
+ @bundle_names_by_invoice_id = {}
58
+ @bundle_keys_by_invoice_id = {}
59
+ @bundles.each do |bundle|
60
+ load_bundle_name_for_timeline(bundle.external_key)
61
+ end
62
+ @invoices.each do |invoice|
63
+ @bundle_names_by_invoice_id[invoice.invoice_id] = Set.new
64
+ @bundle_keys_by_invoice_id[invoice.invoice_id] = Set.new
65
+ (invoice.bundle_keys || '').split(',').each do |bundle_key|
66
+ load_bundle_name_for_timeline(bundle_key)
67
+ @bundle_names_by_invoice_id[invoice.invoice_id] << @bundle_names[bundle_key]
68
+ @bundle_keys_by_invoice_id[invoice.invoice_id] << bundle_key
69
+ end
70
+ end
71
+
72
+ @selected_bundle = params.key?(:external_key) ? @bundle_names[params[:external_key]] : nil
73
+
74
+ csv_string = CSV.generate(headers: true) do |csv|
75
+ csv << ['Effective Date', 'Bundles', 'Even Type', 'Details', 'Reason Code/ Comments']
76
+ if %w[INVOICE ALL].include?(event_type)
77
+ @invoices.each do |invoice_stub|
78
+ invoice = invoice_stub.invoice_id.present? && @invoices_by_id.key?(invoice_stub.invoice_id) ? @invoices_by_id[invoice_stub.invoice_id] : invoice_stub
79
+ target_date = invoice.target_date.present? ? invoice.target_date : '[unknown]'
80
+ bundle_keys = invoice_stub.bundle_keys.present? ? invoice_stub.bundle_keys.split(',').map { |bundle_key| @bundle_names[bundle_key] }.join(', ') : ''
81
+ invoice_details = []
82
+ invoice_details << "Amount: #{invoice.amount_to_money} (#{@account.currency})"
83
+ invoice_details << "Balance: #{invoice.balance_to_money} (#{@account.currency})"
84
+ invoice_details << "Credit adjustment: #{invoice.credit_adjustment_to_money} (#{@account.currency})" if invoice.credit_adj.present? && invoice.credit_adj.positive?
85
+ invoice_details << "Refund adjustment: #{invoice.refund_adjustment_to_money} (#{@account.currency})" if invoice.refund_adj.present? && invoice.refund_adj.negative?
86
+ invoice_details << "Invoice #: #{invoice.invoice_number}"
87
+ audit_logs = invoice_stub.audit_logs.present? ? invoice_stub.audit_logs.map { |entry| Kaui::AuditLog.description(entry) }.join(', ') : ''
88
+ csv << [target_date, bundle_keys, 'INVOICE', invoice_details.join('; '), audit_logs] if filter_date(target_date, start_date, end_date)
89
+ end
90
+ end
91
+ if %w[PAYMENT ALL].include?(event_type)
92
+ @payments.each do |payment|
93
+ invoice = if payment.target_invoice_id.present?
94
+ @invoices_by_id[payment.target_invoice_id]
95
+ else
96
+ nil
97
+ end
98
+
99
+ payment.transactions.each do |transaction|
100
+ effective_date = transaction.effective_date.present? ? transaction.effective_date : '[unknown]'
101
+ bundle_keys = @bundle_keys_by_invoice_id[payment.target_invoice_id].present? ? @bundle_keys_by_invoice_id[payment.target_invoice_id].map { |bundle_key| @bundle_names[bundle_key] }.join(', ') : ''
102
+ transaction_type = transaction.transaction_type
103
+ details = []
104
+ details << "Amount: #{Kaui::Transaction.amount_to_money(transaction)} (#{transaction.currency})" unless transaction.transaction_type == 'VOID'
105
+ details << "Status: #{transaction.status}"
106
+ details << "Payment #: #{payment.payment_number}"
107
+ details << "Invoice #: #{invoice.invoice_number}" unless invoice.nil?
108
+
109
+ audit_logs = transaction.audit_logs.present? ? transaction.audit_logs.map { |entry| Kaui::AuditLog.description(entry) }.chunk { |x| x }.map(&:first).join(', ') : ''
110
+
111
+ csv << [effective_date, bundle_keys, transaction_type, details.join('; '), audit_logs] if filter_date(effective_date, start_date, end_date)
112
+ end
113
+ end
114
+ end
115
+
116
+ if %w[ENTITLEMENT ALL].include?(event_type)
117
+ @bundles.each do |bundle|
118
+ bundle.subscriptions.each do |sub|
119
+ sub.events.each do |event|
120
+ # Skip SERVICE_STATE_CHANGE events
121
+ next if event.event_type == 'SERVICE_STATE_CHANGE'
122
+
123
+ effective_date = event.effective_date.present? ? event.effective_date : '[unknown]'
124
+ bundle_keys = @bundle_names[bundle.external_key]
125
+ event_type = event.event_type
126
+ phase = event.phase
127
+ audit_logs = event.audit_logs.present? ? event.audit_logs.map { |entry| Kaui::AuditLog.description(entry) }.join(', ') : ''
128
+
129
+ csv << [effective_date, bundle_keys, event_type, phase, audit_logs] if filter_date(effective_date, start_date, end_date)
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ send_data csv_string, filename: "account-timelines-#{Date.today}.csv", type: 'text/csv'
137
+ end
138
+
33
139
  private
34
140
 
141
+ def filter_date(target_date, start_date, end_date)
142
+ return true if start_date.nil? || end_date.nil?
143
+
144
+ target_date = begin
145
+ Date.parse(target_date)
146
+ rescue StandardError
147
+ nil
148
+ end
149
+ target_date >= start_date && target_date <= end_date
150
+ end
151
+
35
152
  def load_bundle_name_for_timeline(bundle_key)
36
153
  @bundle_names[bundle_key] ||= Kaui.bundle_key_display_string.call(bundle_key)
37
154
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'csv'
3
4
  module Kaui
4
5
  class AccountsController < Kaui::EngineController
5
6
  def index
@@ -16,6 +17,8 @@ module Kaui
16
17
  return
17
18
  end
18
19
 
20
+ @dropdown_default = default_columns(Kaui.account_search_columns.call[2], Kaui::Account::SENSIVITE_DATA_FIELDS)
21
+
19
22
  @ordering = params[:ordering] || (@search_query.blank? ? 'desc' : 'asc')
20
23
  @offset = params[:offset] || 0
21
24
  @limit = params[:limit] || 50
@@ -39,17 +42,52 @@ module Kaui
39
42
  end
40
43
 
41
44
  formatter = lambda do |account|
42
- child_label = ''
43
- unless account.parent_account_id.nil?
44
- child_label = account.parent_account_id.nil? ? '' : view_context.content_tag(:span, 'Child', class: %w[label label-info account-child-label])
45
+ Kaui.account_search_columns.call(account, view_context)[1]
46
+ end
47
+
48
+ paginate searcher, data_extractor, formatter, default_columns(Kaui.account_search_columns.call[2], Kaui::Account::SENSIVITE_DATA_FIELDS)
49
+ end
50
+
51
+ def download
52
+ start_date = params[:startDate]
53
+ end_date = params[:endDate]
54
+ all_fields_checked = params[:allFieldsChecked] == 'true'
55
+
56
+ if all_fields_checked
57
+ columns = KillBillClient::Model::AccountAttributes.instance_variable_get('@json_attributes')
58
+ else
59
+ columns = params.require(:columnsString).split(',').map { |attr| attr.split.join('_').downcase }
60
+ Kaui::Account::REMAPPING_FIELDS.each do |k, v|
61
+ index = columns.index(v)
62
+ columns[index] = k if index
45
63
  end
64
+ end
46
65
 
47
- row = [child_label, view_context.link_to(account.account_id, view_context.url_for(action: :show, account_id: account.account_id))]
48
- row += Kaui.account_search_columns.call(account, view_context)[1]
49
- row
66
+ start_date = begin
67
+ Date.parse(start_date)
68
+ rescue StandardError
69
+ nil
70
+ end
71
+ end_date = begin
72
+ Date.parse(end_date)
73
+ rescue StandardError
74
+ nil
50
75
  end
76
+ accounts = Kaui::Account.list_or_search(nil, 0, MAXIMUM_NUMBER_OF_RECORDS_DOWNLOAD, options_for_klient)
77
+
78
+ csv_string = CSV.generate(headers: true) do |csv|
79
+ csv << columns
80
+ accounts.each do |account|
81
+ change_date = Date.parse(account.reference_time)
82
+ data = columns.map do |attr|
83
+ account&.send(attr.downcase)
84
+ end
85
+ next if start_date && end_date && change_date && (change_date < start_date || change_date > end_date)
51
86
 
52
- paginate searcher, data_extractor, formatter
87
+ csv << data
88
+ end
89
+ end
90
+ send_data csv_string, filename: "accounts-#{Date.today}.csv", type: 'text/csv'
53
91
  end
54
92
 
55
93
  def new
@@ -331,6 +369,11 @@ module Kaui
331
369
  end
332
370
  end
333
371
 
372
+ def export_account
373
+ data = KillBillClient::Model::Export.find_by_account_id(params[:account_id], current_user.kb_username, options_for_klient)
374
+ send_data data, filename: "account#{params[:account_id]}.txt", type: :txt
375
+ end
376
+
334
377
  private
335
378
 
336
379
  def email_notification_plugin_available?(options_for_klient)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'csv'
4
+
3
5
  module Kaui
4
6
  class AuditLogsController < Kaui::EngineController
5
7
  OBJECT_WITH_HISTORY = %w[ACCOUNT ACCOUNT_EMAIL BLOCKING_STATES BUNDLE CUSTOM_FIELD INVOICE INVOICE_ITEM PAYMENT_ATTEMPT PAYMENT PAYMENT_METHOD SUBSCRIPTION SUBSCRIPTION_EVENT TRANSACTION TAG TAG_DEFINITION].freeze
@@ -42,6 +44,41 @@ module Kaui
42
44
  @audit_logs_json = @audit_logs_json.to_json
43
45
  end
44
46
 
47
+ def download
48
+ account_id = params.require(:account_id)
49
+ start_date = params[:startDate]
50
+ end_date = params[:endDate]
51
+ start_date = begin
52
+ Date.parse(start_date)
53
+ rescue StandardError
54
+ nil
55
+ end
56
+ end_date = begin
57
+ Date.parse(end_date)
58
+ rescue StandardError
59
+ nil
60
+ end
61
+
62
+ account = Kaui::Account.find_by_id_or_key(account_id, false, false, options_for_klient)
63
+ audit_logs = account.audit(options_for_klient)
64
+
65
+ csv_file = CSV.generate do |csv|
66
+ csv << Kaui.account_audit_logs_columns.call[0]
67
+ audit_logs.each do |log|
68
+ change_date = begin
69
+ Date.parse(log.change_date)
70
+ rescue StandardError
71
+ nil
72
+ end
73
+ next if start_date && end_date && change_date && !(change_date > start_date && change_date < end_date)
74
+
75
+ csv << [log.change_date, log.object_id, log.object_type, log.change_type, log.changed_by, log.reason_code, log.comments, log.user_token]
76
+ end
77
+ end
78
+
79
+ send_data csv_file, type: 'text/csv', filename: "audit-logs-#{Date.today}.csv"
80
+ end
81
+
45
82
  def history
46
83
  json_response do
47
84
  account_id = params.require(:account_id)
@@ -5,8 +5,10 @@ module Kaui
5
5
  # rubocop:disable Lint/HashCompareByIdentity
6
6
  def index
7
7
  cached_options_for_klient = options_for_klient
8
+ @per_page = (params[:per_page] || 10).to_i
9
+ @page = (params[:page] || 1).to_i
8
10
 
9
- fetch_bundles = promise { @account.bundles(cached_options_for_klient) }
11
+ fetch_bundles = promise { Kaui::Account.paginated_bundles(@account.account_id, (@page - 1) * @per_page, @per_page, 'NONE', cached_options_for_klient) }
10
12
  fetch_bundle_tags = promise do
11
13
  all_bundle_tags = @account.all_tags(:BUNDLE, false, 'NONE', cached_options_for_klient)
12
14
  all_bundle_tags.each_with_object({}) do |entry, hsh|
@@ -35,6 +37,8 @@ module Kaui
35
37
  fetch_available_subscription_tags = promise { Kaui::TagDefinition.all_for_subscription(cached_options_for_klient) }
36
38
 
37
39
  @bundles = wait(fetch_bundles)
40
+ @total_pages = (@bundles.pagination_max_nb_records.to_f / @per_page).ceil
41
+
38
42
  @tags_per_bundle = wait(fetch_bundle_tags)
39
43
  @tags_per_subscription = wait(fetch_subscription_tags)
40
44
  @custom_fields_per_bundle = wait(fetch_bundle_fields)
@@ -1,6 +1,9 @@
1
+ require_relative '../../../lib/kaui/error_handler'
2
+
1
3
  class Kaui::EngineController < ApplicationController
2
4
 
3
5
  include Kaui::EngineControllerUtil
6
+ include Kaui::ErrorHandler
4
7
 
5
8
  before_action :authenticate_user!, :check_for_redirect_to_tenant_screen, :populate_account_details
6
9
 
@@ -59,25 +62,6 @@ class Kaui::EngineController < ApplicationController
59
62
  end
60
63
  end
61
64
 
62
- # Note! Order matters, StandardError needs to be first
63
- rescue_from(StandardError) do |error|
64
- flash[:error] = "Error: #{as_string(error)}"
65
- try_to_redirect_to_account_path = !params[:controller].ends_with?('accounts')
66
- perform_redirect_after_error try_to_redirect_to_account_path
67
- end
68
-
69
- rescue_from(ActionController::ParameterMissing) do |parameter_missing_exception|
70
- log_rescue_error parameter_missing_exception
71
- flash[:error] = "Required parameter missing: #{parameter_missing_exception.param}"
72
- perform_redirect_after_error
73
- end
74
-
75
- rescue_from(KillBillClient::API::ResponseError) do |killbill_exception|
76
- flash[:error] = "Error while communicating with the Kill Bill server: #{as_string(killbill_exception)}"
77
- try_to_redirect_to_account_path = !killbill_exception.is_a?(KillBillClient::API::Unauthorized) && !(killbill_exception.is_a?(KillBillClient::API::NotFound) && params[:controller].ends_with?('accounts'))
78
- perform_redirect_after_error try_to_redirect_to_account_path
79
- end
80
-
81
65
  private
82
66
 
83
67
  def current_tenant_user
@@ -95,13 +79,4 @@ class Kaui::EngineController < ApplicationController
95
79
  end
96
80
  result
97
81
  end
98
-
99
- def perform_redirect_after_error(try_to_redirect_to_account_path = true)
100
- account_id = nested_hash_value(params.permit!.to_h, :account_id)
101
- if try_to_redirect_to_account_path && account_id.present?
102
- redirect_to kaui_engine.account_path(account_id)
103
- else
104
- redirect_to kaui_engine.home_path
105
- end
106
- end
107
82
  end
@@ -4,6 +4,7 @@ module Kaui
4
4
  module EngineControllerUtil
5
5
  # See DefaultPaginationSqlDaoHelper.java
6
6
  SIMPLE_PAGINATION_THRESHOLD = 20_000
7
+ MAXIMUM_NUMBER_OF_RECORDS_DOWNLOAD = 1000
7
8
 
8
9
  protected
9
10
 
@@ -13,7 +14,7 @@ module Kaui
13
14
  end
14
15
  # rubocop:enable Lint/UselessAssignment, Naming/AccessorMethodName
15
16
 
16
- def paginate(searcher, data_extractor, formatter)
17
+ def paginate(searcher, data_extractor, formatter, table_default_columns = [])
17
18
  search_key = (params[:search] || {})[:value].presence
18
19
  offset = (params[:start] || 0).to_i
19
20
  limit = (params[:length] || 10).to_i
@@ -30,7 +31,8 @@ module Kaui
30
31
  # We need to fill-in a number to make DataTables happy
31
32
  recordsTotal: pages.nil? ? 0 : (pages.pagination_max_nb_records || SIMPLE_PAGINATION_THRESHOLD),
32
33
  recordsFiltered: pages.nil? ? 0 : (pages.pagination_total_nb_records || SIMPLE_PAGINATION_THRESHOLD),
33
- data: []
34
+ data: [],
35
+ columns: table_default_columns
34
36
  }
35
37
  json[:error] = error unless error.nil?
36
38
 
@@ -151,5 +153,9 @@ module Kaui
151
153
  end
152
154
  render json: response, status: response_status
153
155
  end
156
+
157
+ def default_columns(fields, sensivite_fields)
158
+ fields.map { |field| { data: fields.index(field), visible: !(sensivite_fields.include? field) } }
159
+ end
154
160
  end
155
161
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'csv'
3
4
  module Kaui
4
5
  class InvoicesController < Kaui::EngineController
5
6
  def index
@@ -12,6 +13,37 @@ module Kaui
12
13
  @max_nb_records = @search_query.blank? ? Kaui::Invoice.list_or_search(nil, 0, 0, options_for_klient).pagination_max_nb_records : 0
13
14
  end
14
15
 
16
+ def download
17
+ account_id = params[:account_id]
18
+ start_date = params[:startDate]
19
+ end_date = params[:endDate]
20
+ all_fields_checked = params[:allFieldsChecked] == 'true'
21
+ columns = if all_fields_checked
22
+ KillBillClient::Model::InvoiceAttributes.instance_variable_get('@json_attributes') - Kaui::Invoice::TABLE_IGNORE_COLUMNS
23
+ else
24
+ params.require(:columnsString).split(',').map { |attr| attr.split.join('_').downcase }
25
+ end
26
+
27
+ kb_params = {}
28
+ kb_params[:startDate] = Date.parse(start_date).strftime('%Y-%m-%d') if start_date
29
+ kb_params[:endDate] = Date.parse(end_date).strftime('%Y-%m-%d') if end_date
30
+ if account_id.present?
31
+ account = Kaui::Account.find_by_id_or_key(account_id, false, false, options_for_klient)
32
+ invoices = account.invoices(options_for_klient.merge(params: kb_params))
33
+ else
34
+ invoices = Kaui::Invoice.list_or_search(nil, 0, MAXIMUM_NUMBER_OF_RECORDS_DOWNLOAD, options_for_klient.merge(params: kb_params))
35
+ end
36
+
37
+ csv_string = CSV.generate(headers: true) do |csv|
38
+ csv << columns
39
+
40
+ invoices.each do |invoice|
41
+ csv << columns.map { |attr| invoice&.send(attr.downcase) }
42
+ end
43
+ end
44
+ send_data csv_string, filename: "invoices-#{Date.today}.csv", type: 'text/csv'
45
+ end
46
+
15
47
  def pagination
16
48
  cached_options_for_klient = options_for_klient
17
49
 
@@ -24,39 +56,32 @@ module Kaui
24
56
  if account.nil?
25
57
  Kaui::Invoice.list_or_search(search_key, offset, limit, cached_options_for_klient)
26
58
  else
27
- account.invoices(cached_options_for_klient.merge({ params: { includeVoidedInvoices: true } })).map! { |invoice| Kaui::Invoice.build_from_raw_invoice(invoice) }
59
+ Kaui::Account.paginated_invoices(search_key, offset, limit, 'NONE', cached_options_for_klient).map! { |invoice| Kaui::Invoice.build_from_raw_invoice(invoice) }
28
60
  end
29
61
  end
30
62
 
31
63
  account_id = (params[:search] || {})[:value]
32
- if account_id.blank?
33
- # Don't show amount and balance, and they will not be populated
34
- data_extractor = lambda do |invoice, column|
35
- [
36
- invoice.invoice_number.to_i,
37
- invoice.invoice_date
38
- ][column]
39
- end
40
- formatter = lambda do |invoice|
41
- row = [view_context.link_to(invoice.invoice_number, view_context.url_for(controller: :invoices, action: :show, account_id: invoice.account_id, id: invoice.invoice_id))]
42
- row += Kaui.invoice_search_columns.call(invoice, view_context, cached_options_for_klient)[1]
43
- row
44
- end
45
- else
46
- data_extractor = lambda do |invoice, column|
47
- [
48
- invoice.invoice_number.to_i,
49
- invoice.invoice_date,
50
- invoice.amount,
51
- invoice.balance,
52
- invoice.status
53
- ][column]
54
- end
55
- formatter = lambda do |invoice|
56
- row = [view_context.link_to(invoice.invoice_number, view_context.url_for(controller: :invoices, action: :show, account_id: invoice.account_id, id: invoice.invoice_id))]
57
- row += Kaui.account_invoices_columns.call(invoice, view_context)[1]
58
- row
59
- end
64
+ data_extractor = if account_id.blank?
65
+ lambda do |invoice, column|
66
+ [
67
+ invoice.invoice_number.to_i,
68
+ invoice.invoice_date
69
+ ][column]
70
+ end
71
+ else
72
+ lambda do |invoice, column|
73
+ [
74
+ invoice.invoice_number.to_i,
75
+ invoice.invoice_date,
76
+ invoice.amount,
77
+ invoice.balance,
78
+ invoice.status
79
+ ][column]
80
+ end
81
+ end
82
+
83
+ formatter = lambda do |invoice|
84
+ Kaui.account_invoices_columns.call(invoice, view_context)[1]
60
85
  end
61
86
 
62
87
  paginate searcher, data_extractor, formatter
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'csv'
4
+
3
5
  module Kaui
4
6
  class PaymentsController < Kaui::EngineController
5
7
  def index
@@ -12,7 +14,72 @@ module Kaui
12
14
  @max_nb_records = @search_query.blank? ? Kaui::Payment.list_or_search(nil, 0, 0, options_for_klient).pagination_max_nb_records : 0
13
15
  end
14
16
 
17
+ def download
18
+ account_id = params[:account_id]
19
+ start_date = params[:startDate]
20
+ end_date = params[:endDate]
21
+ all_fields_checked = params[:allFieldsChecked] == 'true'
22
+ if all_fields_checked
23
+ columns = KillBillClient::Model::PaymentAttributes.instance_variable_get('@json_attributes') - %w[transactions audit_logs]
24
+ else
25
+ columns = params.require(:columnsString).split(',').map { |attr| attr.split.join('_').downcase }
26
+ Kaui::Payment::REMAPPING_FIELDS.each do |k, v|
27
+ index = columns.index(v)
28
+ columns[index] = k if index
29
+ end
30
+ end
31
+
32
+ kb_params = {}
33
+ kb_params[:startDate] = Date.parse(start_date).strftime('%Y-%m-%d') if start_date
34
+ kb_params[:endDate] = Date.parse(end_date).strftime('%Y-%m-%d') if end_date
35
+ if account_id.present?
36
+ account = Kaui::Account.find_by_id_or_key(account_id, false, false, options_for_klient)
37
+ payments = account.payments(options_for_klient).map! { |payment| Kaui::Payment.build_from_raw_payment(payment) }
38
+ else
39
+ payments = Kaui::Payment.list_or_search(nil, 0, MAXIMUM_NUMBER_OF_RECORDS_DOWNLOAD, options_for_klient.merge(params: kb_params))
40
+ end
41
+
42
+ payments.each do |payment|
43
+ created_date = nil
44
+ payment.transactions.each do |transaction|
45
+ transaction_date = Date.parse(transaction.effective_date)
46
+ created_date = transaction_date if created_date.nil? || (transaction_date < created_date)
47
+ end
48
+ payment.payment_date = created_date
49
+ end
50
+
51
+ csv_string = CSV.generate(headers: true) do |csv|
52
+ csv << columns
53
+
54
+ payments.each do |payment|
55
+ next if start_date && end_date && (payment.payment_date < Date.parse(start_date) || payment.payment_date > Date.parse(end_date))
56
+
57
+ data = columns.map do |attr|
58
+ case attr
59
+ when 'payment_number'
60
+ payment.payment_number
61
+ when 'payment_date'
62
+ view_context.format_date(payment.payment_date, account&.time_zone)
63
+ when 'total_authed_amount_to_money'
64
+ view_context.humanized_money_with_symbol(payment.total_authed_amount_to_money)
65
+ when 'paid_amount_to_money'
66
+ view_context.humanized_money_with_symbol(payment.paid_amount_to_money)
67
+ when 'returned_amount_to_money'
68
+ view_context.humanized_money_with_symbol(payment.returned_amount_to_money)
69
+ when 'status'
70
+ payment.transactions.empty? ? nil : payment.transactions[-1].status
71
+ else
72
+ payment&.send(attr.downcase)
73
+ end
74
+ end
75
+ csv << data
76
+ end
77
+ end
78
+ send_data csv_string, filename: "payments-#{Date.today}.csv", type: 'text/csv'
79
+ end
80
+
15
81
  def pagination
82
+ account = nil
16
83
  searcher = lambda do |search_key, offset, limit|
17
84
  if Kaui::Payment::TRANSACTION_STATUSES.include?(search_key)
18
85
  # Search is done by payment state on the server side, see http://docs.killbill.io/latest/userguide_payment.html#_payment_states
@@ -30,6 +97,7 @@ module Kaui
30
97
  rescue StandardError
31
98
  nil
32
99
  end
100
+
33
101
  payments = if account.nil?
34
102
  Kaui::Payment.list_or_search(search_key, offset, limit, options_for_klient)
35
103
  else
@@ -62,15 +130,7 @@ module Kaui
62
130
  end
63
131
 
64
132
  formatter = lambda do |payment|
65
- [
66
- view_context.link_to(payment.payment_number, view_context.url_for(controller: :payments, action: :show, account_id: payment.account_id, id: payment.payment_id)),
67
- view_context.format_date(payment.payment_date, @account.time_zone),
68
- view_context.humanized_money_with_symbol(payment.total_authed_amount_to_money),
69
- view_context.humanized_money_with_symbol(payment.paid_amount_to_money),
70
- view_context.humanized_money_with_symbol(payment.returned_amount_to_money),
71
- payment.transactions.empty? ? nil : view_context.colored_transaction_status(payment.transactions[-1].status),
72
- payment.payment_external_key
73
- ]
133
+ Kaui.account_payments_columns.call(account, payment, view_context)[1]
74
134
  end
75
135
 
76
136
  paginate searcher, data_extractor, formatter
@@ -3,12 +3,19 @@
3
3
  module Kaui
4
4
  # Subclassed to specify the correct layout
5
5
  class SessionsController < Devise::SessionsController
6
+ include Kaui::ExceptionHelper
7
+
6
8
  layout Kaui.config[:layout]
7
9
 
8
10
  skip_before_action :check_for_redirect_to_tenant_screen, raise: false
9
11
 
10
12
  # The sign-in flow eventually calls authenticate! from config/initializers/killbill_authenticatable.rb
11
13
 
14
+ rescue_from(StandardError) do |exception|
15
+ @error = standardize_exception(exception)
16
+ render 'kaui/errors/500', status: 500, layout: false
17
+ end
18
+
12
19
  protected
13
20
 
14
21
  # Override after_sign_in_path_for to not have to rely on the default 'root' config which we want to keep on home#index
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaui
4
+ module ExceptionHelper
5
+ def standardize_exception(exception)
6
+ if defined?(JRUBY_VERSION)
7
+ case exception
8
+ when ActiveRecord::JDBCError
9
+ return I18n.translate('errors.messages.unable_to_connect_database')
10
+ end
11
+ end
12
+
13
+ case exception
14
+ when ActiveRecord::DatabaseConnectionError
15
+ I18n.translate('errors.messages.unable_to_connect_database')
16
+ when Errno::ECONNREFUSED, Errno::EBADF
17
+ I18n.translate('errors.messages.unable_to_connect_killbill')
18
+ when ->(e) { e.class.name.start_with?('KillBillClient::API') }
19
+ I18n.translate('errors.messages.error_communicating_killbill')
20
+ else
21
+ nil
22
+ end
23
+ end
24
+ end
25
+ end
@@ -98,7 +98,7 @@ module Kaui
98
98
  ''
99
99
  else
100
100
  current_plan = sub.prices.select { |price| price['phaseType'] == sub.phase_type && price['planName'] == sub.plan_name }
101
- price_override = current_plan.last['fixedPrice'] || current_plan.last['recurringPrice']
101
+ price_override = current_plan.last ? (current_plan.last['fixedPrice'] || current_plan.last['recurringPrice']) : nil
102
102
 
103
103
  if price_override.blank?
104
104
  ''
@@ -172,5 +172,9 @@ module Kaui
172
172
  def subscription_cancelled?(sub)
173
173
  sub.present? and sub.billing_end_date.present?
174
174
  end
175
+
176
+ def paging_button_class(num, current_page)
177
+ num == current_page ? 'btn btn-primary' : 'btn btn-custom'
178
+ end
175
179
  end
176
180
  end