kaui 3.0.2 → 3.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/kaui/logo.svg +37 -0
  3. data/app/controllers/kaui/account_timelines_controller.rb +121 -0
  4. data/app/controllers/kaui/accounts_controller.rb +51 -14
  5. data/app/controllers/kaui/admin_tenants_controller.rb +19 -6
  6. data/app/controllers/kaui/audit_logs_controller.rb +40 -3
  7. data/app/controllers/kaui/bundles_controller.rb +5 -1
  8. data/app/controllers/kaui/charges_controller.rb +1 -1
  9. data/app/controllers/kaui/credits_controller.rb +1 -1
  10. data/app/controllers/kaui/custom_fields_controller.rb +3 -3
  11. data/app/controllers/kaui/engine_controller.rb +3 -28
  12. data/app/controllers/kaui/engine_controller_util.rb +8 -2
  13. data/app/controllers/kaui/home_controller.rb +5 -5
  14. data/app/controllers/kaui/invoice_items_controller.rb +1 -1
  15. data/app/controllers/kaui/invoices_controller.rb +59 -34
  16. data/app/controllers/kaui/payment_methods_controller.rb +3 -3
  17. data/app/controllers/kaui/payments_controller.rb +66 -10
  18. data/app/controllers/kaui/refunds_controller.rb +3 -2
  19. data/app/controllers/kaui/sessions_controller.rb +7 -0
  20. data/app/controllers/kaui/subscriptions_controller.rb +8 -8
  21. data/app/controllers/kaui/transactions_controller.rb +2 -2
  22. data/app/helpers/kaui/exception_helper.rb +25 -0
  23. data/app/helpers/kaui/subscription_helper.rb +4 -0
  24. data/app/models/kaui/account.rb +2 -0
  25. data/app/models/kaui/custom_field.rb +1 -1
  26. data/app/models/kaui/invoice.rb +2 -0
  27. data/app/models/kaui/payment_method.rb +4 -4
  28. data/app/views/kaui/account_timelines/_multi_functions_bar.html.erb +184 -0
  29. data/app/views/kaui/account_timelines/show.html.erb +2 -0
  30. data/app/views/kaui/accounts/_account_info.html.erb +7 -0
  31. data/app/views/kaui/accounts/_multi_functions_bar.html.erb +347 -0
  32. data/app/views/kaui/accounts/index.html.erb +46 -33
  33. data/app/views/kaui/audit_logs/_multi_functions_bar.html.erb +218 -0
  34. data/app/views/kaui/audit_logs/index.html.erb +1 -0
  35. data/app/views/kaui/bundles/index.html.erb +34 -0
  36. data/app/views/kaui/errors/500.html.erb +29 -0
  37. data/app/views/kaui/invoices/_multi_functions_bar.html.erb +340 -0
  38. data/app/views/kaui/invoices/index.html.erb +41 -19
  39. data/app/views/kaui/layouts/kaui_navbar.html.erb +1 -1
  40. data/app/views/kaui/payments/_multi_functions_bar.html.erb +344 -0
  41. data/app/views/kaui/payments/index.html.erb +64 -25
  42. data/config/locales/en.yml +3 -0
  43. data/config/routes.rb +7 -0
  44. data/lib/kaui/error_handler.rb +37 -0
  45. data/lib/kaui/version.rb +1 -1
  46. data/lib/kaui.rb +105 -29
  47. data/lib/tasks/kaui_tasks.rake +1 -0
  48. metadata +11 -3
  49. data/app/assets/images/kaui/logo.png +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95dc79de55c417e61d67883ec040660bb28923268cc479b3fa0d027689bd007f
4
- data.tar.gz: 722db58817b35d95ae08be67a131b85b1706868d73d0182bfa267a7007ea5eb2
3
+ metadata.gz: 381a1791f9fc6c1d64886d34dca17905a83ec38322043735a2437d83d8516d35
4
+ data.tar.gz: ee79517525bb910a58c1996621171c0600c113e98215e016f283f5d3ee9d2c0e
5
5
  SHA512:
6
- metadata.gz: '091113972ba008f89462c312ea46f05f0510ed64dff52ecd5522af6eff02f8c61aeaea8cf92d89a405d6a893dfc1ee12f86268f895b3b77107a08722ba185f08'
7
- data.tar.gz: bb5a5b1901b527d519503ca1a406afc86ac44025e51303ba6ab24403515c3ce61f2c2337d863db238418fbada9057243346be53c3e69547160ceaf0337b6c074
6
+ metadata.gz: bce25f97853968fb171263eb1513ca6588d4884e0045232880bc24bc10cd55057b36e72cd89a7ef86996c4c9ec045a0b37aa7f39a35c2c9dfe0137866e1d7255
7
+ data.tar.gz: 371aa14f4390357331e257e9735a1c4f2ac940069b041f7bf595f68c960fec3c3ca32af274ba39b3abf4047a5e8d789590bbb6b90b079a11236bd7ee1b89de1a
@@ -0,0 +1,37 @@
1
+ <svg width="138" height="36" viewBox="0 0 138 36" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M8.96891 13.6363L17.1663 16.2316L19.867 20.7179L7.22926 20.294L5.87472 17.7276C4.70442 15.5102 6.6717 12.9089 8.96891 13.6363Z" fill="url(#paint0_linear_5656_117635)"/>
3
+ <path d="M2.73109 18.8862L23.0656 19.4261L31.0472 32.6526C31.9039 34.0722 30.9562 35.9453 29.3786 35.9506L14.6421 36C12.8282 36.0061 11.0908 35.2177 9.83259 33.8178L0.749744 23.712C-0.899153 21.8774 0.354861 18.8231 2.73109 18.8862Z" fill="url(#paint1_linear_5656_117635)"/>
4
+ <path d="M20.5179 0.919922L15.7246 7.75567L23.189 11.3725L24.8913 4.89582L20.5179 0.919922Z" fill="url(#paint2_linear_5656_117635)"/>
5
+ <path d="M27.5141 34.8764L15.4574 13.4093C14.4372 11.5929 14.565 9.35199 15.785 7.66255C16.4888 6.68792 17.8875 6.54241 18.778 7.35118L34.1718 21.3321C36.1567 23.1348 36.5779 26.0884 35.1757 28.371L31.1361 34.9469C30.2983 36.3107 28.2978 36.2717 27.5141 34.8764Z" fill="url(#paint3_linear_5656_117635)"/>
6
+ <path d="M32.0753 11.0799L21.0977 3.84213C19.1972 2.5891 20.3796 -0.360792 22.623 0.0364992L27.8828 0.967948C29.1553 1.19329 30.1995 2.09954 30.5986 3.32489L32.9165 10.4422C33.0801 10.9445 32.5171 11.3713 32.0753 11.0799Z" fill="url(#paint4_linear_5656_117635)"/>
7
+ <path d="M69.3857 29.5787C68.2643 29.5787 67.3552 28.684 67.3552 27.5803V14.5758C67.3552 13.4721 68.2643 12.5774 69.3857 12.5774C70.5072 12.5774 71.4163 13.4721 71.4163 14.5758V27.5803C71.4163 28.684 70.5072 29.5787 69.3857 29.5787ZM69.402 9.77566C68.6439 9.77566 68.0158 9.54218 67.5176 9.07523C67.0411 8.60827 66.8028 8.04581 66.8028 7.38783C66.8028 6.70862 67.0411 6.14616 67.5176 5.70043C68.0158 5.23348 68.6439 5 69.402 5C70.1601 5 70.7773 5.22286 71.2539 5.66859C71.752 6.0931 72.0011 6.63434 72.0011 7.29231C72.0011 7.99274 71.7629 8.58705 71.2863 9.07523C70.8098 9.54218 70.1817 9.77566 69.402 9.77566Z" fill="#293056"/>
8
+ <path d="M77.4776 29.5787C76.3561 29.5787 75.447 28.684 75.447 27.5803V7.9536C75.447 6.84988 76.3561 5.95513 77.4776 5.95513C78.599 5.95513 79.5081 6.84988 79.5081 7.9536V27.5803C79.5081 28.684 78.599 29.5787 77.4776 29.5787Z" fill="#293056"/>
9
+ <path d="M85.5694 29.5787C84.4479 29.5787 83.5388 28.684 83.5388 27.5803V7.9536C83.5388 6.84987 84.4479 5.95513 85.5694 5.95513C86.6908 5.95513 87.6 6.84988 87.6 7.9536V27.5803C87.6 28.684 86.6908 29.5787 85.5694 29.5787Z" fill="#293056"/>
10
+ <path d="M119.786 29.5787C118.664 29.5787 117.755 28.684 117.755 27.5803V14.5758C117.755 13.4721 118.664 12.5774 119.786 12.5774C120.907 12.5774 121.816 13.4721 121.816 14.5758V27.5803C121.816 28.684 120.907 29.5787 119.786 29.5787ZM119.802 9.77566C119.044 9.77566 118.416 9.54218 117.918 9.07523C117.441 8.60827 117.203 8.04581 117.203 7.38783C117.203 6.70862 117.441 6.14616 117.918 5.70043C118.416 5.23348 119.044 5 119.802 5C120.56 5 121.177 5.22286 121.654 5.66859C122.152 6.0931 122.401 6.63434 122.401 7.29231C122.401 7.99274 122.163 8.58705 121.686 9.07523C121.21 9.54218 120.582 9.77566 119.802 9.77566Z" fill="#293056"/>
11
+ <path d="M127.878 29.5787C126.756 29.5787 125.847 28.684 125.847 27.5803V7.9536C125.847 6.84987 126.756 5.95513 127.878 5.95513C128.999 5.95513 129.908 6.84988 129.908 7.9536V27.5803C129.908 28.684 128.999 29.5787 127.878 29.5787Z" fill="#293056"/>
12
+ <path d="M135.969 29.5787C134.848 29.5787 133.939 28.684 133.939 27.5803V7.9536C133.939 6.84987 134.848 5.95513 135.969 5.95513C137.091 5.95513 138 6.84988 138 7.9536V27.5803C138 28.684 137.091 29.5787 135.969 29.5787Z" fill="#293056"/>
13
+ <path d="M59.977 13.0294C60.2978 12.7387 60.7179 12.5774 61.1539 12.5774C62.702 12.5774 63.4773 14.4195 62.3826 15.4968L58.1099 19.7015L63.5453 26.4787C64.552 27.734 63.6435 29.5787 62.0187 29.5787C61.4331 29.5787 60.8787 29.319 60.5094 28.8718L55.0817 22.2982L52.0611 25.0975V27.5803C52.0611 28.684 51.152 29.5787 50.0306 29.5787C48.9091 29.5787 48 28.684 48 27.5803V7.9536C48 6.84987 48.9091 5.95513 50.0306 5.95513C51.152 5.95513 52.0611 6.84988 52.0611 7.9536V20.2027L59.977 13.0294Z" fill="#293056"/>
14
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M106.399 29.8016C104.926 29.8016 103.615 29.4832 102.468 28.8465C101.774 28.4618 101.168 27.9611 100.648 27.3441V27.6762C100.648 28.7269 99.7826 29.5787 98.715 29.5787C97.6474 29.5787 96.7819 28.7269 96.7819 27.6762V7.9536C96.7819 6.84987 97.691 5.95513 98.8125 5.95513C99.9339 5.95513 100.843 6.84988 100.843 7.9536V14.6575C101.337 14.1191 101.9 13.6804 102.532 13.3415C103.702 12.7047 104.991 12.3864 106.399 12.3864C108.11 12.3864 109.615 12.7472 110.915 13.4688C112.236 14.1905 113.276 15.1987 114.034 16.4934C114.813 17.7882 115.203 19.3164 115.203 21.0781C115.203 22.8397 114.813 24.3679 114.034 25.6627C113.276 26.9574 112.236 27.9762 110.915 28.7191C109.615 29.4408 108.11 29.8016 106.399 29.8016ZM108.543 25.7582C107.785 26.1827 106.919 26.395 105.944 26.395C104.969 26.395 104.092 26.1827 103.312 25.7582C102.532 25.3337 101.915 24.7182 101.46 23.9116C101.006 23.1051 100.778 22.1605 100.778 21.0781C100.778 19.9743 101.006 19.0298 101.46 18.2445C101.915 17.4379 102.532 16.8224 103.312 16.3979C104.092 15.9734 104.969 15.7612 105.944 15.7612C106.919 15.7612 107.785 15.9734 108.543 16.3979C109.323 16.8224 109.94 17.4379 110.395 18.2445C110.85 19.0298 111.077 19.9743 111.077 21.0781C111.077 22.1605 110.85 23.1051 110.395 23.9116C109.94 24.7182 109.323 25.3337 108.543 25.7582Z" fill="#293056"/>
15
+ <defs>
16
+ <linearGradient id="paint0_linear_5656_117635" x1="6.3713" y1="14.584" x2="17.3232" y2="20.2038" gradientUnits="userSpaceOnUse">
17
+ <stop stop-color="#004EEB"/>
18
+ <stop offset="1" stop-color="#2970FF"/>
19
+ </linearGradient>
20
+ <linearGradient id="paint1_linear_5656_117635" x1="1.04487" y1="21.155" x2="29.4032" y2="32.4876" gradientUnits="userSpaceOnUse">
21
+ <stop stop-color="#2970FF"/>
22
+ <stop offset="1" stop-color="#7CD4FD"/>
23
+ </linearGradient>
24
+ <linearGradient id="paint2_linear_5656_117635" x1="19.8881" y1="9.67384" x2="23.8884" y2="4.93559" gradientUnits="userSpaceOnUse">
25
+ <stop stop-color="#A6EF67"/>
26
+ <stop offset="1" stop-color="#FDE172"/>
27
+ </linearGradient>
28
+ <linearGradient id="paint3_linear_5656_117635" x1="15.1997" y1="8.83686" x2="29.3077" y2="34.3257" gradientUnits="userSpaceOnUse">
29
+ <stop stop-color="#A6EF67"/>
30
+ <stop offset="1" stop-color="#15B79E"/>
31
+ </linearGradient>
32
+ <linearGradient id="paint4_linear_5656_117635" x1="20.833" y1="1.40851" x2="32.7401" y2="9.43028" gradientUnits="userSpaceOnUse">
33
+ <stop stop-color="#FDE172"/>
34
+ <stop offset="1" stop-color="#EAAA08"/>
35
+ </linearGradient>
36
+ </defs>
37
+ </svg>
@@ -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
@@ -115,10 +148,9 @@ module Kaui
115
148
  end
116
149
 
117
150
  fetch_payment_methods_with_details = fetch_payment_methods.then do |pms|
118
- ops = []
119
- pms.each do |pm|
120
- ops << promise do
121
- Kaui::PaymentMethod.find_by_id(pm.payment_method_id, true, cached_options_for_klient)
151
+ ops = pms.map do |pm|
152
+ promise do
153
+ Kaui::PaymentMethod.find_by_id(pm.payment_method_id, false, true, [], 'NONE', cached_options_for_klient)
122
154
  rescue StandardError => e
123
155
  # Maybe the plugin is not registered or the plugin threw an exception
124
156
  Rails.logger.warn(e)
@@ -182,7 +214,7 @@ module Kaui
182
214
  invoice = nil
183
215
  begin
184
216
  invoice = if dry_run
185
- Kaui::Invoice.trigger_invoice_dry_run(account_id, target_date, false, options_for_klient)
217
+ Kaui::Invoice.trigger_invoice_dry_run(account_id, target_date, false, [], current_user.kb_username, params[:reason], params[:comment], options_for_klient)
186
218
  else
187
219
  Kaui::Invoice.trigger_invoice(account_id, target_date, current_user.kb_username, params[:reason], params[:comment], options_for_klient)
188
220
  end
@@ -209,7 +241,7 @@ module Kaui
209
241
  # Fetched asynchronously, as it takes time. This also helps with enforcing permissions.
210
242
  def next_invoice_date
211
243
  json_response do
212
- next_invoice = Kaui::Invoice.trigger_invoice_dry_run(params.require(:account_id), nil, true, options_for_klient)
244
+ next_invoice = Kaui::Invoice.trigger_invoice_dry_run(params.require(:account_id), nil, true, [], current_user.kb_username, params[:reason], params[:comment], options_for_klient)
213
245
  next_invoice ? next_invoice.target_date.to_json : nil
214
246
  end
215
247
  end
@@ -332,6 +364,11 @@ module Kaui
332
364
  end
333
365
  end
334
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
+
335
372
  private
336
373
 
337
374
  def email_notification_plugin_available?(options_for_klient)
@@ -130,9 +130,23 @@ module Kaui
130
130
  uploaded_catalog = params.require(:catalog)
131
131
  catalog_xml = uploaded_catalog.read
132
132
 
133
- Kaui::AdminTenant.upload_catalog(catalog_xml, options[:username], nil, comment, options)
134
-
135
- redirect_to admin_tenant_path(current_tenant.id), notice: I18n.translate('flashes.notices.catalog_uploaded_successfully')
133
+ validate_response = Kaui::Catalog.validate_catalog(catalog_xml, options[:username], nil, comment, options)
134
+ catalog_validation_errors = begin
135
+ JSON.parse(validate_response.response.body)['catalogValidationErrors']
136
+ rescue StandardError
137
+ nil
138
+ end
139
+ if catalog_validation_errors.blank?
140
+ Kaui::AdminTenant.upload_catalog(catalog_xml, options[:username], nil, comment, options)
141
+ redirect_to admin_tenant_path(current_tenant.id), notice: I18n.translate('flashes.notices.catalog_uploaded_successfully')
142
+ else
143
+ errors = ''
144
+ catalog_validation_errors.each do |validation_error|
145
+ errors += (validation_error['errorDescription'])
146
+ end
147
+ flash[:error] = errors
148
+ redirect_to admin_tenant_new_catalog_path(id: current_tenant.id)
149
+ end
136
150
  end
137
151
 
138
152
  def new_catalog
@@ -441,9 +455,8 @@ module Kaui
441
455
 
442
456
  # convert result to a full hash since dynamic attributes of a class are ignored when converting to json
443
457
  result.each do |data|
444
- plans = []
445
- data[:plans].each do |plan|
446
- plans << plan.instance_variables.each_with_object({}) { |var, hash_plan| hash_plan[var.to_s.delete('@')] = plan.instance_variable_get(var) }
458
+ plans = data[:plans].map do |plan|
459
+ plan.instance_variables.each_with_object({}) { |var, hash_plan| hash_plan[var.to_s.delete('@')] = plan.instance_variable_get(var) }
447
460
  end
448
461
 
449
462
  catalog << { version_date: data[:version_date],
@@ -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)
@@ -68,7 +105,7 @@ module Kaui
68
105
  when 'CUSTOM_FIELD'
69
106
  audit_logs_with_history = Kaui::CustomField.new({ custom_field_id: object_id }).audit_logs_with_history(cached_options_for_klient)
70
107
  when 'INVOICE'
71
- invoice = Kaui::Invoice.find_by_id(object_id, 'NONE', cached_options_for_klient)
108
+ invoice = Kaui::Invoice.find_by_id(object_id, false, 'NONE', cached_options_for_klient)
72
109
  audit_logs_with_history = invoice.audit_logs_with_history(cached_options_for_klient)
73
110
  when 'INVOICE_ITEM'
74
111
  invoice_item = Kaui::InvoiceItem.new
@@ -84,10 +121,10 @@ module Kaui
84
121
  payment = Kaui::Payment.find_by_id(object_id, false, false, cached_options_for_klient)
85
122
  audit_logs_with_history = payment.audit_logs_with_history(cached_options_for_klient)
86
123
  when 'PAYMENT_METHOD'
87
- payment_method = Kaui::PaymentMethod.find_by_id(object_id, false, cached_options_for_klient)
124
+ payment_method = Kaui::PaymentMethod.find_by_id(object_id, false, false, [], 'NONE', cached_options_for_klient)
88
125
  audit_logs_with_history = payment_method.audit_logs_with_history(cached_options_for_klient)
89
126
  when 'SUBSCRIPTION'
90
- subscription = Kaui::Subscription.find_by_id(object_id, cached_options_for_klient)
127
+ subscription = Kaui::Subscription.find_by_id(object_id, 'NONE', cached_options_for_klient)
91
128
  audit_logs_with_history = subscription.audit_logs_with_history(cached_options_for_klient)
92
129
  when 'SUBSCRIPTION_EVENT'
93
130
  audit_logs_with_history = Kaui::Subscription.event_audit_logs_with_history(object_id, cached_options_for_klient)
@@ -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)
@@ -7,7 +7,7 @@ module Kaui
7
7
  amount = params[:amount]
8
8
 
9
9
  if invoice_id.present?
10
- @invoice = Kaui::Invoice.find_by_id(invoice_id, 'NONE', options_for_klient)
10
+ @invoice = Kaui::Invoice.find_by_id(invoice_id, false, 'NONE', options_for_klient)
11
11
  amount ||= @invoice.balance
12
12
  currency = @invoice.currency
13
13
  else
@@ -7,7 +7,7 @@ module Kaui
7
7
  amount = params[:amount]
8
8
 
9
9
  if invoice_id.present?
10
- @invoice = Kaui::Invoice.find_by_id(invoice_id, 'NONE', options_for_klient)
10
+ @invoice = Kaui::Invoice.find_by_id(invoice_id, false, 'NONE', options_for_klient)
11
11
  amount ||= @invoice.balance
12
12
  currency = @invoice.currency
13
13
  else
@@ -71,7 +71,7 @@ module Kaui
71
71
  end
72
72
  when :SUBSCRIPTION
73
73
  begin
74
- test_uuid = Kaui::Subscription.find_by_id(param_uuid, options_for_klient)
74
+ test_uuid = Kaui::Subscription.find_by_id(param_uuid, 'NONE', options_for_klient)
75
75
  rescue StandardError
76
76
  # Ignore
77
77
  end
@@ -163,7 +163,7 @@ module Kaui
163
163
  end
164
164
  when 'SUBSCRIPTION'
165
165
  begin
166
- test_uuid = Kaui::Subscription.find_by_id(param_uuid, options_for_klient)
166
+ test_uuid = Kaui::Subscription.find_by_id(param_uuid, 'NONE', options_for_klient)
167
167
  rescue StandardError
168
168
  # Ignore
169
169
  ensure
@@ -172,7 +172,7 @@ module Kaui
172
172
  when 'INVOICE'
173
173
  begin
174
174
  cached_options_for_klient = options_for_klient
175
- test_uuid = Kaui::Invoice.find_by_id(param_uuid, 'FULL', cached_options_for_klient)
175
+ test_uuid = Kaui::Invoice.find_by_id(param_uuid, false, 'FULL', cached_options_for_klient)
176
176
  rescue StandardError
177
177
  # Ignore
178
178
  ensure
@@ -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
@@ -55,7 +55,7 @@ module Kaui
55
55
  case search_by
56
56
  when 'ID'
57
57
  begin
58
- invoice = Kaui::Invoice.find_by_id(search_query, 'NONE', options)
58
+ invoice = Kaui::Invoice.find_by_id(search_query, false, 'NONE', options)
59
59
  redirect_to account_invoice_path(invoice.account_id, invoice.invoice_id) and return
60
60
  rescue KillBillClient::API::NotFound => _e
61
61
  search_error("No invoice matches \"#{search_query}\"")
@@ -64,7 +64,7 @@ module Kaui
64
64
  unsupported_search_field('INVOICE', search_by)
65
65
  when 'NUMBER'
66
66
  begin
67
- invoice = Kaui::Invoice.find_by_number(search_query, 'NONE', options)
67
+ invoice = Kaui::Invoice.find_by_number(search_query, false, 'NONE', options)
68
68
  redirect_to account_invoice_path(invoice.account_id, invoice.invoice_id) and return
69
69
  rescue KillBillClient::API::NotFound, KillBillClient::API::BadRequest => _e
70
70
  search_error("No invoice matches \"#{search_query}\"")
@@ -116,14 +116,14 @@ module Kaui
116
116
  def transaction_search(search_query, search_by = nil, _fast = 0, options = {})
117
117
  if search_by.blank? || search_by == 'ID'
118
118
  begin
119
- payment = Kaui::Payment.find_by_transaction_id(search_query, false, true, options)
119
+ payment = Kaui::Payment.find_by_transaction_id(search_query, false, true, [], 'NONE', options)
120
120
  redirect_to account_payment_path(payment.account_id, payment.payment_id) and return
121
121
  rescue KillBillClient::API::NotFound => _e
122
122
  search_error("No transaction matches \"#{search_query}\"")
123
123
  end
124
124
  else
125
125
  begin
126
- payment = Kaui::Payment.find_by_transaction_external_key(search_query, false, true, 'NONE', options)
126
+ payment = Kaui::Payment.find_by_transaction_external_key(search_query, false, true, [], 'NONE', options)
127
127
  redirect_to account_payment_path(payment.account_id, payment.payment_id) and return
128
128
  rescue KillBillClient::API::NotFound => _e
129
129
  search_error("No transaction matches \"#{search_query}\"")
@@ -198,7 +198,7 @@ module Kaui
198
198
  def subscription_search(search_query, search_by = nil, _fast = 0, options = {})
199
199
  if search_by.blank? || search_by == 'ID'
200
200
  begin
201
- subscription = Kaui::Subscription.find_by_id(search_query, options)
201
+ subscription = Kaui::Subscription.find_by_id(search_query, 'NONE', options)
202
202
  redirect_to account_bundles_path(subscription.account_id) and return
203
203
  rescue KillBillClient::API::NotFound => _e
204
204
  search_error("No subscription matches \"#{search_query}\"")
@@ -7,7 +7,7 @@ module Kaui
7
7
  invoice_id = params.require(:invoice_id)
8
8
 
9
9
  # See https://github.com/killbill/killbill/issues/7
10
- invoice = Kaui::Invoice.find_by_id(invoice_id, 'NONE', options_for_klient)
10
+ invoice = Kaui::Invoice.find_by_id(invoice_id, false, 'NONE', options_for_klient)
11
11
  @invoice_item = invoice.items.find { |ii| ii.invoice_item_id == invoice_item_id }
12
12
 
13
13
  return unless @invoice_item.nil?