kaui 3.0.3 → 3.0.5

Sign up to get free protection for your applications and to get access to all the features.
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