kaui 3.0.3 → 3.0.4

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/kaui/account_timelines_controller.rb +121 -0
  3. data/app/controllers/kaui/accounts_controller.rb +46 -8
  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 +65 -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 +4 -0
  13. data/app/models/kaui/account.rb +2 -0
  14. data/app/models/kaui/invoice.rb +2 -0
  15. data/app/views/kaui/account_timelines/_multi_functions_bar.html.erb +184 -0
  16. data/app/views/kaui/account_timelines/show.html.erb +2 -0
  17. data/app/views/kaui/accounts/_account_info.html.erb +7 -0
  18. data/app/views/kaui/accounts/_multi_functions_bar.html.erb +347 -0
  19. data/app/views/kaui/accounts/index.html.erb +46 -33
  20. data/app/views/kaui/audit_logs/_multi_functions_bar.html.erb +218 -0
  21. data/app/views/kaui/audit_logs/index.html.erb +1 -0
  22. data/app/views/kaui/bundles/index.html.erb +34 -0
  23. data/app/views/kaui/errors/500.html.erb +29 -0
  24. data/app/views/kaui/invoices/_multi_functions_bar.html.erb +340 -0
  25. data/app/views/kaui/invoices/index.html.erb +41 -19
  26. data/app/views/kaui/payments/_multi_functions_bar.html.erb +344 -0
  27. data/app/views/kaui/payments/index.html.erb +64 -25
  28. data/config/locales/en.yml +3 -0
  29. data/config/routes.rb +7 -0
  30. data/lib/kaui/error_handler.rb +37 -0
  31. data/lib/kaui/version.rb +1 -1
  32. data/lib/kaui.rb +105 -29
  33. metadata +10 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fdb45a75d2f3a57307ffe426a864911262563d623f25cccefd3941de52655e36
4
- data.tar.gz: f45cbd12e90f63dfb544743381af6c4a2dbeab58fe0671334f02198bdeb97323
3
+ metadata.gz: 381a1791f9fc6c1d64886d34dca17905a83ec38322043735a2437d83d8516d35
4
+ data.tar.gz: ee79517525bb910a58c1996621171c0600c113e98215e016f283f5d3ee9d2c0e
5
5
  SHA512:
6
- metadata.gz: 065274ae77055af9c3a54b7938f8c8f0d09775b5d7a7b4e953c990790ad7e4af247096b287f308062e53f09b13d16eda146ccd893c762baa3dc7ab644f8a3c01
7
- data.tar.gz: 15cd32d52a680d624be8bf85f3db439f1afc78ad5d7308054fecf7aad66d130f8a5bd324ec93ba7fd140399be84f4eec6015e1c9a054f55f368f8c4202ecebfb
6
+ metadata.gz: bce25f97853968fb171263eb1513ca6588d4884e0045232880bc24bc10cd55057b36e72cd89a7ef86996c4c9ec045a0b37aa7f39a35c2c9dfe0137866e1d7255
7
+ data.tar.gz: 371aa14f4390357331e257e9735a1c4f2ac940069b041f7bf595f68c960fec3c3ca32af274ba39b3abf4047a5e8d789590bbb6b90b079a11236bd7ee1b89de1a
@@ -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,127 @@ 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 = params[:startDate]
38
+ end_date = params[:endDate]
39
+ start_date = begin
40
+ Date.parse(start_date)
41
+ rescue StandardError
42
+ nil
43
+ end
44
+ end_date = begin
45
+ Date.parse(end_date)
46
+ rescue StandardError
47
+ nil
48
+ end
49
+ start_date = params[:startDate].present? ? Date.parse(params[:startDate]) : nil
50
+ end_date = params[:endDate].present? ? Date.parse(params[:endDate]) : nil
51
+
52
+ event_type = params[:eventType]
53
+ @account = timeline.account
54
+ @bundles = timeline.bundles
55
+ @invoices = timeline.invoices
56
+ @payments = timeline.payments
57
+ extract_invoices_by_id(@invoices)
58
+
59
+ # Lookup all bundle names
60
+ @bundle_names = {}
61
+ @bundle_names_by_invoice_id = {}
62
+ @bundle_keys_by_invoice_id = {}
63
+ @bundles.each do |bundle|
64
+ load_bundle_name_for_timeline(bundle.external_key)
65
+ end
66
+ @invoices.each do |invoice|
67
+ @bundle_names_by_invoice_id[invoice.invoice_id] = Set.new
68
+ @bundle_keys_by_invoice_id[invoice.invoice_id] = Set.new
69
+ (invoice.bundle_keys || '').split(',').each do |bundle_key|
70
+ load_bundle_name_for_timeline(bundle_key)
71
+ @bundle_names_by_invoice_id[invoice.invoice_id] << @bundle_names[bundle_key]
72
+ @bundle_keys_by_invoice_id[invoice.invoice_id] << bundle_key
73
+ end
74
+ end
75
+
76
+ @selected_bundle = params.key?(:external_key) ? @bundle_names[params[:external_key]] : nil
77
+
78
+ csv_string = CSV.generate(headers: true) do |csv|
79
+ csv << ['Effective Date', 'Bundles', 'Even Type', 'Details', 'Reason Code/ Comments']
80
+ if %w[INVOICE ALL].include?(event_type)
81
+ @invoices.each do |invoice_stub|
82
+ invoice = invoice_stub.invoice_id.present? && @invoices_by_id.key?(invoice_stub.invoice_id) ? @invoices_by_id[invoice_stub.invoice_id] : invoice_stub
83
+ target_date = invoice.target_date.present? ? invoice.target_date : '[unknown]'
84
+ bundle_keys = invoice_stub.bundle_keys.present? ? invoice_stub.bundle_keys.split(',').map { |bundle_key| @bundle_names[bundle_key] }.join(', ') : ''
85
+ invoice_details = []
86
+ invoice_details << "Amount: #{invoice.amount_to_money} (#{@account.currency})"
87
+ invoice_details << "Balance: #{invoice.balance_to_money} (#{@account.currency})"
88
+ invoice_details << "Credit adjustment: #{invoice.credit_adjustment_to_money} (#{@account.currency})" if invoice.credit_adj.present? && invoice.credit_adj.positive?
89
+ invoice_details << "Refund adjustment: #{invoice.refund_adjustment_to_money} (#{@account.currency})" if invoice.refund_adj.present? && invoice.refund_adj.negative?
90
+ invoice_details << "Invoice #: #{invoice.invoice_number}"
91
+ audit_logs = invoice_stub.audit_logs.present? ? invoice_stub.audit_logs.map { |entry| Kaui::AuditLog.description(entry) }.join(', ') : ''
92
+ csv << [target_date, bundle_keys, 'INVOICE', invoice_details.join('; '), audit_logs] if filter_date(target_date, start_date, end_date)
93
+ end
94
+ end
95
+ if %w[PAYMENT ALL].include?(event_type)
96
+ @payments.each do |payment|
97
+ invoice = if payment.target_invoice_id.present?
98
+ @invoices_by_id[payment.target_invoice_id]
99
+ else
100
+ nil
101
+ end
102
+
103
+ payment.transactions.each do |transaction|
104
+ effective_date = transaction.effective_date.present? ? transaction.effective_date : '[unknown]'
105
+ 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(', ') : ''
106
+ transaction_type = transaction.transaction_type
107
+ details = []
108
+ details << "Amount: #{Kaui::Transaction.amount_to_money(transaction)} (#{transaction.currency})" unless transaction.transaction_type == 'VOID'
109
+ details << "Status: #{transaction.status}"
110
+ details << "Payment #: #{payment.payment_number}"
111
+ details << "Invoice #: #{invoice.invoice_number}" unless invoice.nil?
112
+
113
+ audit_logs = transaction.audit_logs.present? ? transaction.audit_logs.map { |entry| Kaui::AuditLog.description(entry) }.chunk { |x| x }.map(&:first).join(', ') : ''
114
+
115
+ csv << [effective_date, bundle_keys, transaction_type, details.join('; '), audit_logs] if filter_date(effective_date, start_date, end_date)
116
+ end
117
+ end
118
+ end
119
+
120
+ if %w[ENTITLEMENT ALL].include?(event_type)
121
+ @bundles.each do |bundle|
122
+ bundle.subscriptions.each do |sub|
123
+ sub.events.each do |event|
124
+ # Skip SERVICE_STATE_CHANGE events
125
+ next if event.event_type == 'SERVICE_STATE_CHANGE'
126
+
127
+ effective_date = event.effective_date.present? ? event.effective_date : '[unknown]'
128
+ bundle_keys = @bundle_names[bundle.external_key]
129
+ event_type = event.event_type
130
+ phase = event.phase
131
+ audit_logs = event.audit_logs.present? ? event.audit_logs.map { |entry| Kaui::AuditLog.description(entry) }.join(', ') : ''
132
+
133
+ csv << [effective_date, bundle_keys, event_type, phase, audit_logs] if filter_date(effective_date, start_date, end_date)
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ send_data csv_string, filename: "account-timelines-#{Date.today}.csv", type: 'text/csv'
141
+ end
142
+
33
143
  private
34
144
 
145
+ def filter_date(target_date, start_date, end_date)
146
+ return true if start_date.nil? || end_date.nil?
147
+
148
+ target_date = begin
149
+ Date.parse(target_date)
150
+ rescue StandardError
151
+ nil
152
+ end
153
+ target_date >= start_date && target_date <= end_date
154
+ end
155
+
35
156
  def load_bundle_name_for_timeline(bundle_key)
36
157
  @bundle_names[bundle_key] ||= Kaui.bundle_key_display_string.call(bundle_key)
37
158
  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,47 @@ 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
- end
45
+ Kaui.account_search_columns.call(account, view_context)[1]
46
+ end
46
47
 
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
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
+ columns = if all_fields_checked
57
+ KillBillClient::Model::AccountAttributes.instance_variable_get('@json_attributes')
58
+ else
59
+ params.require(:columnsString).split(',').map { |attr| attr.split.join('_').downcase }
60
+ end
61
+ start_date = begin
62
+ Date.parse(start_date)
63
+ rescue StandardError
64
+ nil
65
+ end
66
+ end_date = begin
67
+ Date.parse(end_date)
68
+ rescue StandardError
69
+ nil
50
70
  end
71
+ accounts = Kaui::Account.list_or_search(nil, 0, MAXIMUM_NUMBER_OF_RECORDS_DOWNLOAD, options_for_klient)
72
+
73
+ csv_string = CSV.generate(headers: true) do |csv|
74
+ csv << columns
75
+ accounts.each do |account|
76
+ change_date = Date.parse(account.reference_time)
77
+ data = columns.map do |attr|
78
+ account&.send(attr.downcase)
79
+ end
80
+ next if start_date && end_date && change_date && (change_date < start_date || change_date > end_date)
51
81
 
52
- paginate searcher, data_extractor, formatter
82
+ csv << data
83
+ end
84
+ end
85
+ send_data csv_string, filename: "accounts-#{Date.today}.csv", type: 'text/csv'
53
86
  end
54
87
 
55
88
  def new
@@ -331,6 +364,11 @@ module Kaui
331
364
  end
332
365
  end
333
366
 
367
+ def export_account
368
+ data = KillBillClient::Model::Export.find_by_account_id(params[:account_id], current_user.kb_username, options_for_klient)
369
+ send_data data, filename: "account#{params[:account_id]}.txt", type: :txt
370
+ end
371
+
334
372
  private
335
373
 
336
374
  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_#{account_id}.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,68 @@ 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
+ columns = if all_fields_checked
23
+ KillBillClient::Model::PaymentAttributes.instance_variable_get('@json_attributes') - %w[transactions audit_logs]
24
+ else
25
+ params.require(:columnsString).split(',').map { |attr| attr.split.join('_').downcase }
26
+ end
27
+
28
+ kb_params = {}
29
+ kb_params[:startDate] = Date.parse(start_date).strftime('%Y-%m-%d') if start_date
30
+ kb_params[:endDate] = Date.parse(end_date).strftime('%Y-%m-%d') if end_date
31
+ if account_id.present?
32
+ account = Kaui::Account.find_by_id_or_key(account_id, false, false, options_for_klient)
33
+ payments = account.payments(options_for_klient).map! { |payment| Kaui::Payment.build_from_raw_payment(payment) }
34
+ else
35
+ payments = Kaui::Payment.list_or_search(nil, 0, MAXIMUM_NUMBER_OF_RECORDS_DOWNLOAD, options_for_klient.merge(params: kb_params))
36
+ end
37
+
38
+ payments.each do |payment|
39
+ created_date = nil
40
+ payment.transactions.each do |transaction|
41
+ transaction_date = Date.parse(transaction.effective_date)
42
+ created_date ||= transaction_date if transaction_date < created_date
43
+ end
44
+ payment.payment_date = created_date
45
+ end
46
+
47
+ csv_string = CSV.generate(headers: true) do |csv|
48
+ csv << columns
49
+
50
+ payments.each do |payment|
51
+ next if start_date && end_date && (payment.payment_date < Date.parse(start_date) || payment.payment_date > Date.parse(end_date))
52
+
53
+ data = columns.map do |attr|
54
+ case attr
55
+ when 'payment_number'
56
+ payment.payment_number
57
+ when 'payment_date'
58
+ view_context.format_date(payment.payment_date, account&.time_zone)
59
+ when 'total_authed_amount_to_money'
60
+ view_context.humanized_money_with_symbol(payment.total_authed_amount_to_money)
61
+ when 'paid_amount_to_money'
62
+ view_context.humanized_money_with_symbol(payment.paid_amount_to_money)
63
+ when 'returned_amount_to_money'
64
+ view_context.humanized_money_with_symbol(payment.returned_amount_to_money)
65
+ when 'status'
66
+ payment.transactions.empty? ? nil : payment.transactions[-1].status
67
+ else
68
+ payment&.send(attr.downcase)
69
+ end
70
+ end
71
+ csv << data
72
+ end
73
+ end
74
+ send_data csv_string, filename: "payments-#{Date.today}.csv", type: 'text/csv'
75
+ end
76
+
15
77
  def pagination
78
+ account = nil
16
79
  searcher = lambda do |search_key, offset, limit|
17
80
  if Kaui::Payment::TRANSACTION_STATUSES.include?(search_key)
18
81
  # Search is done by payment state on the server side, see http://docs.killbill.io/latest/userguide_payment.html#_payment_states
@@ -30,6 +93,7 @@ module Kaui
30
93
  rescue StandardError
31
94
  nil
32
95
  end
96
+
33
97
  payments = if account.nil?
34
98
  Kaui::Payment.list_or_search(search_key, offset, limit, options_for_klient)
35
99
  else
@@ -62,15 +126,7 @@ module Kaui
62
126
  end
63
127
 
64
128
  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
- ]
129
+ Kaui.account_payments_columns.call(account, payment, view_context)[1]
74
130
  end
75
131
 
76
132
  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
@@ -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
@@ -4,6 +4,8 @@ module Kaui
4
4
  class Account < KillBillClient::Model::Account
5
5
  attr_accessor :phone, :bill_cycle_day_local
6
6
 
7
+ SENSIVITE_DATA_FIELDS = %w[name email].freeze
8
+
7
9
  def check_account_details_phone
8
10
  return true if phone =~ /\A(?:\+?\d{1,3}\s*-?)?\(?(?:\d{3})?\)?[- ]?\d{3}[- ]?\d{4}\z/i
9
11
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Kaui
4
4
  class Invoice < KillBillClient::Model::Invoice
5
+ TABLE_IGNORE_COLUMNS = %w[amount balance credit_adj refund_adj items is_parent_invoice parent_invoice_id parent_account_id].freeze
6
+
5
7
  def self.build_from_raw_invoice(raw_invoice)
6
8
  result = Kaui::Invoice.new
7
9
  KillBillClient::Model::InvoiceAttributes.instance_variable_get('@json_attributes').each do |attr|