kaui 3.0.6 → 3.0.7
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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/kaui/multi_functions_bar_utils.js +132 -0
- data/app/controllers/kaui/account_timelines_controller.rb +1 -1
- data/app/controllers/kaui/accounts_controller.rb +13 -4
- data/app/controllers/kaui/engine_controller_util.rb +26 -0
- data/app/controllers/kaui/invoices_controller.rb +10 -7
- data/app/controllers/kaui/payments_controller.rb +19 -8
- data/app/controllers/kaui/sessions_controller.rb +2 -0
- data/app/helpers/kaui/exception_helper.rb +3 -1
- data/app/models/kaui/account.rb +4 -1
- data/app/models/kaui/invoice.rb +2 -0
- data/app/models/kaui/payment.rb +2 -0
- data/app/views/kaui/accounts/_account_filterbar.html.erb +189 -0
- data/app/views/kaui/accounts/_multi_functions_bar.html.erb +41 -2
- data/app/views/kaui/accounts/index.html.erb +6 -11
- data/app/views/kaui/invoices/_invoice_filterbar.html.erb +204 -0
- data/app/views/kaui/invoices/_multi_functions_bar.html.erb +17 -2
- data/app/views/kaui/invoices/index.html.erb +12 -5
- data/app/views/kaui/payments/_multi_functions_bar.html.erb +17 -2
- data/app/views/kaui/payments/_payment_filterbar.html.erb +190 -0
- data/app/views/kaui/payments/index.html.erb +7 -6
- data/lib/kaui/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23207942c5d84c906aa3e23e06c74e86f278b7889088efb260bbb7d591043b4b
|
4
|
+
data.tar.gz: 56df3037f7210cffd9521a410df4302d93da6e5c3989bc5717fbad37033fcb9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5542399f26a14547366266fd4047b78cada6204033610005d9901e8d1a8c7a2367423809e468f599d602e1e59880c0f08cfded1298deeef41bc593e4203592de
|
7
|
+
data.tar.gz: eff5e260361d301bf8cc10ac973320c25f9fb76347aa57b3792017acc6fb4d817cea4e798eb797bf6d7c575862b5e1b4bf62ceed2d036ab33611f66f62a28e15
|
@@ -0,0 +1,132 @@
|
|
1
|
+
// Function to map operators to user-friendly text
|
2
|
+
function searchFormatOperator(operator) {
|
3
|
+
var operatorMapping = {
|
4
|
+
'eq': 'Equals',
|
5
|
+
'neq': 'Not Equals',
|
6
|
+
'gt': 'Greater Than',
|
7
|
+
'gte': 'Greater Than Or Equal',
|
8
|
+
'lt': 'Less Than',
|
9
|
+
'lte': 'Less Than Or Equal',
|
10
|
+
'like': 'Like'
|
11
|
+
};
|
12
|
+
return operatorMapping[operator] || operator;
|
13
|
+
}
|
14
|
+
|
15
|
+
// Function to parse URL parameters
|
16
|
+
function getUrlParams() {
|
17
|
+
var params = {};
|
18
|
+
var queryString = window.location.search.substring(1);
|
19
|
+
queryString = queryString.replace(/ac_id/g, 'account_id');
|
20
|
+
var regex = /([^&=]+)=([^&]*)/g;
|
21
|
+
var m;
|
22
|
+
while (m = regex.exec(queryString)) {
|
23
|
+
params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
|
24
|
+
}
|
25
|
+
return params;
|
26
|
+
}
|
27
|
+
|
28
|
+
// Function to populate search labels from URL parameters
|
29
|
+
function populateSearchLabelsFromUrl() {
|
30
|
+
var params = getUrlParams();
|
31
|
+
var searchLabelsContainer = $('#search-labels-container');
|
32
|
+
searchLabelsContainer.empty();
|
33
|
+
|
34
|
+
var hasBalanceFilter = window.location.search.includes('balance');
|
35
|
+
|
36
|
+
for (var key in params) {
|
37
|
+
if (params.hasOwnProperty(key)) {
|
38
|
+
var value = params[key];
|
39
|
+
value = value.replace(/%/g, '');
|
40
|
+
var match = key.match(/(.*)\[(.*)\]/);
|
41
|
+
if (match) {
|
42
|
+
var columnName = match[1].replace(/_/g, ' ').replace(/^\w/, function(l) { return l.toUpperCase(); });
|
43
|
+
var filter = searchFormatOperator(match[2]);
|
44
|
+
var label = $('<span>', {
|
45
|
+
class: 'label label-info',
|
46
|
+
text: columnName + ' [' + filter + '] ' + value
|
47
|
+
});
|
48
|
+
|
49
|
+
if (hasBalanceFilter && columnName.toLowerCase() !== 'balance') {
|
50
|
+
label.attr('class', 'label label-default');
|
51
|
+
}
|
52
|
+
|
53
|
+
searchLabelsContainer.append(label);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
function searchQuery(account_id){
|
60
|
+
var searchFields = $('.search-field');
|
61
|
+
var searchLabelsContainer = $('#search-labels-container');
|
62
|
+
searchLabelsContainer.empty();
|
63
|
+
|
64
|
+
var searchLabels = searchFields.map(function() {
|
65
|
+
var filter = $(this).find('.search-field-filter').val();
|
66
|
+
var value = $(this).find('.search-field-value').val();
|
67
|
+
var columnName = $(this).find('.search-field-filter').attr('name').replace('Filter', '').toLowerCase().replace(/\s+/g, '_');
|
68
|
+
|
69
|
+
if (value !== '') {
|
70
|
+
if (filter === 'like') {
|
71
|
+
return columnName + encodeURIComponent('[' + filter + ']') + '=' + encodeURIComponent('%' + value + '%');
|
72
|
+
} else {
|
73
|
+
return columnName + encodeURIComponent('[' + filter + ']') + '=' + encodeURIComponent(value);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}).get().join('&');
|
77
|
+
|
78
|
+
if (account_id !== undefined && account_id !== '') {
|
79
|
+
searchLabels += '&' + encodeURIComponent('account_id[eq]') + '=' + encodeURIComponent(account_id);
|
80
|
+
}
|
81
|
+
|
82
|
+
var searchLabelString = searchLabels.length > 0 ? ('_q=1&' + searchLabels) : '';
|
83
|
+
if (searchLabelString == '') {
|
84
|
+
clearAdvanceSearch();
|
85
|
+
}
|
86
|
+
return searchLabelString;
|
87
|
+
};
|
88
|
+
|
89
|
+
function clearAdvanceSearch() {
|
90
|
+
// Clear all search fields
|
91
|
+
$('#search-fields-container').empty();
|
92
|
+
|
93
|
+
// Remove all search labels
|
94
|
+
$('#search-labels-container').empty();
|
95
|
+
|
96
|
+
// Reload the page with the original URL (no parameters)
|
97
|
+
window.location.href = window.location.pathname;
|
98
|
+
|
99
|
+
// Hide the modal
|
100
|
+
$('#advanceSearchModal').modal('hide');
|
101
|
+
}
|
102
|
+
|
103
|
+
function showAdvanceSearchModal() {
|
104
|
+
var searchLabelsContainer = $('#search-labels-container');
|
105
|
+
var searchFieldsContainer = $('#search-fields-container');
|
106
|
+
searchFieldsContainer.empty();
|
107
|
+
|
108
|
+
// Populate the search fields with the current filters
|
109
|
+
searchLabelsContainer.find('.label').each(function() {
|
110
|
+
var labelText = $(this).text();
|
111
|
+
var parts = labelText.split(' [');
|
112
|
+
var columnName = parts[0].trim();
|
113
|
+
var filterAndValue = parts[1].split('] ');
|
114
|
+
var filter = filterAndValue[0].trim();
|
115
|
+
var value = filterAndValue[1].trim();
|
116
|
+
|
117
|
+
var template = document.getElementById('search-field-template').content.cloneNode(true);
|
118
|
+
template.querySelector('.search-field-label').textContent = columnName.replace(/([A-Z])/g, ' $1').trim();
|
119
|
+
template.querySelector('.search-field-filter').name = columnName + 'Filter';
|
120
|
+
template.querySelector('.search-field-filter').value = filter;
|
121
|
+
template.querySelector('.search-field-value').name = columnName;
|
122
|
+
template.querySelector('.search-field-value').value = value;
|
123
|
+
|
124
|
+
searchFieldsContainer.append(template);
|
125
|
+
var dropdown = searchFieldsContainer.find('.search-field:last-child .search-field-filter');
|
126
|
+
dropdown.find('option').each(function() {
|
127
|
+
if ($(this).text().trim().toLowerCase() === filter.toLowerCase()) {
|
128
|
+
$(this).prop('selected', true);
|
129
|
+
}
|
130
|
+
});
|
131
|
+
});
|
132
|
+
}
|
@@ -5,7 +5,7 @@ module Kaui
|
|
5
5
|
class AccountsController < Kaui::EngineController
|
6
6
|
def index
|
7
7
|
@search_query = params[:q]
|
8
|
-
|
8
|
+
@advance_search_query = request.query_string
|
9
9
|
if params[:fast] == '1' && !@search_query.blank?
|
10
10
|
account = Kaui::Account.list_or_search(@search_query, -1, 1, options_for_klient).first
|
11
11
|
if account.nil?
|
@@ -16,7 +16,7 @@ module Kaui
|
|
16
16
|
end
|
17
17
|
return
|
18
18
|
end
|
19
|
-
|
19
|
+
@search_fields = Kaui::Account::ADVANCED_SEARCH_COLUMNS.map { |attr| [attr, attr.split('_').join(' ').capitalize] }
|
20
20
|
@dropdown_default = default_columns(Kaui.account_search_columns.call[2], Kaui::Account::SENSIVITE_DATA_FIELDS)
|
21
21
|
|
22
22
|
@ordering = params[:ordering] || (@search_query.blank? ? 'desc' : 'asc')
|
@@ -29,6 +29,7 @@ module Kaui
|
|
29
29
|
def pagination
|
30
30
|
cached_options_for_klient = options_for_klient
|
31
31
|
searcher = lambda do |search_key, offset, limit|
|
32
|
+
search_key = remapping_addvanced_search_fields(search_key, Kaui::Account::ADVANCED_SEARCH_NAME_CHANGES)
|
32
33
|
Kaui::Account.list_or_search(search_key, offset, limit, cached_options_for_klient)
|
33
34
|
end
|
34
35
|
|
@@ -52,11 +53,18 @@ module Kaui
|
|
52
53
|
start_date = params[:startDate]
|
53
54
|
end_date = params[:endDate]
|
54
55
|
all_fields_checked = params[:allFieldsChecked] == 'true'
|
56
|
+
query_string = params[:search]
|
55
57
|
|
56
58
|
if all_fields_checked
|
57
59
|
columns = KillBillClient::Model::AccountAttributes.instance_variable_get('@json_attributes')
|
60
|
+
csv_headers = columns.dup
|
61
|
+
Kaui::Account::REMAPPING_FIELDS.each do |k, v|
|
62
|
+
index = csv_headers.index(k)
|
63
|
+
csv_headers[index] = v if index
|
64
|
+
end
|
58
65
|
else
|
59
66
|
columns = params.require(:columnsString).split(',').map { |attr| attr.split.join('_').downcase }
|
67
|
+
csv_headers = columns.dup
|
60
68
|
Kaui::Account::REMAPPING_FIELDS.each do |k, v|
|
61
69
|
index = columns.index(v)
|
62
70
|
columns[index] = k if index
|
@@ -73,10 +81,11 @@ module Kaui
|
|
73
81
|
rescue StandardError
|
74
82
|
nil
|
75
83
|
end
|
76
|
-
|
84
|
+
query_string = remapping_addvanced_search_fields(query_string, Kaui::Account::ADVANCED_SEARCH_NAME_CHANGES)
|
85
|
+
accounts = Kaui::Account.list_or_search(query_string, 0, MAXIMUM_NUMBER_OF_RECORDS_DOWNLOAD, options_for_klient)
|
77
86
|
|
78
87
|
csv_string = CSV.generate(headers: true) do |csv|
|
79
|
-
csv <<
|
88
|
+
csv << csv_headers
|
80
89
|
accounts.each do |account|
|
81
90
|
change_date = Date.parse(account.reference_time)
|
82
91
|
data = columns.map do |attr|
|
@@ -14,8 +14,34 @@ module Kaui
|
|
14
14
|
end
|
15
15
|
# rubocop:enable Lint/UselessAssignment, Naming/AccessorMethodName
|
16
16
|
|
17
|
+
# Remove this when we support balance search alongside the other search
|
18
|
+
def handle_balance_search(query_string)
|
19
|
+
return nil if query_string.blank?
|
20
|
+
return query_string unless query_string.include?('balance')
|
21
|
+
|
22
|
+
CGI.unescape(query_string)
|
23
|
+
.split('&')
|
24
|
+
.grep(/_q|balance/)
|
25
|
+
.map { |param| param.split('=') }
|
26
|
+
.map { |key, value| "#{CGI.escape(key)}=#{value}" }
|
27
|
+
.join('&')
|
28
|
+
end
|
29
|
+
|
30
|
+
def remapping_addvanced_search_fields(search_string, advanced_search_name_changes)
|
31
|
+
return search_string if search_string.blank? || !(search_string.include? '_q')
|
32
|
+
|
33
|
+
advanced_search_name_changes.each do |new_name, old_name|
|
34
|
+
search_string = search_string.gsub(new_name, old_name)
|
35
|
+
end
|
36
|
+
search_string
|
37
|
+
end
|
38
|
+
|
17
39
|
def paginate(searcher, data_extractor, formatter, table_default_columns = [])
|
18
40
|
search_key = (params[:search] || {})[:value].presence
|
41
|
+
advance_search_query = params[:advance_search_query].presence
|
42
|
+
|
43
|
+
search_key = advance_search_query if advance_search_query
|
44
|
+
search_key = handle_balance_search(search_key) if search_key.present?
|
19
45
|
offset = (params[:start] || 0).to_i
|
20
46
|
limit = (params[:length] || 10).to_i
|
21
47
|
|
@@ -5,10 +5,11 @@ module Kaui
|
|
5
5
|
class InvoicesController < Kaui::EngineController
|
6
6
|
def index
|
7
7
|
@search_query = params[:account_id]
|
8
|
-
|
8
|
+
@advance_search_query = request.query_string
|
9
9
|
@ordering = params[:ordering] || (@search_query.blank? ? 'desc' : 'asc')
|
10
10
|
@offset = params[:offset] || 0
|
11
11
|
@limit = params[:limit] || 50
|
12
|
+
@search_fields = Kaui::Invoice::ADVANCED_SEARCH_COLUMNS.map { |attr| [attr, attr.split('_').join(' ').capitalize] }
|
12
13
|
|
13
14
|
@max_nb_records = @search_query.blank? ? Kaui::Invoice.list_or_search(nil, 0, 0, options_for_klient).pagination_max_nb_records : 0
|
14
15
|
end
|
@@ -18,6 +19,7 @@ module Kaui
|
|
18
19
|
start_date = params[:startDate]
|
19
20
|
end_date = params[:endDate]
|
20
21
|
all_fields_checked = params[:allFieldsChecked] == 'true'
|
22
|
+
query_string = handle_balance_search(params[:search])
|
21
23
|
columns = if all_fields_checked
|
22
24
|
KillBillClient::Model::InvoiceAttributes.instance_variable_get('@json_attributes') - Kaui::Invoice::TABLE_IGNORE_COLUMNS
|
23
25
|
else
|
@@ -27,12 +29,12 @@ module Kaui
|
|
27
29
|
kb_params = {}
|
28
30
|
kb_params[:startDate] = Date.parse(start_date).strftime('%Y-%m-%d') if start_date
|
29
31
|
kb_params[:endDate] = Date.parse(end_date).strftime('%Y-%m-%d') if end_date
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
query_string = remapping_addvanced_search_fields(query_string, Kaui::Invoice::ADVANCED_SEARCH_NAME_CHANGES)
|
33
|
+
invoices = if account_id.present? && query_string.blank?
|
34
|
+
Kaui::Account.paginated_invoices(account_id, nil, nil, 'NONE', options_for_klient).map! { |invoice| Kaui::Invoice.build_from_raw_invoice(invoice) }
|
35
|
+
else
|
36
|
+
Kaui::Invoice.list_or_search(query_string, 0, MAXIMUM_NUMBER_OF_RECORDS_DOWNLOAD, options_for_klient.merge(params: kb_params))
|
37
|
+
end
|
36
38
|
|
37
39
|
csv_string = CSV.generate(headers: true) do |csv|
|
38
40
|
csv << columns
|
@@ -54,6 +56,7 @@ module Kaui
|
|
54
56
|
nil
|
55
57
|
end
|
56
58
|
if account.nil?
|
59
|
+
search_key = remapping_addvanced_search_fields(search_key, Kaui::Invoice::ADVANCED_SEARCH_NAME_CHANGES)
|
57
60
|
Kaui::Invoice.list_or_search(search_key, offset, limit, cached_options_for_klient)
|
58
61
|
else
|
59
62
|
Kaui::Account.paginated_invoices(search_key, offset, limit, 'NONE', cached_options_for_klient).map! { |invoice| Kaui::Invoice.build_from_raw_invoice(invoice) }
|
@@ -6,10 +6,11 @@ module Kaui
|
|
6
6
|
class PaymentsController < Kaui::EngineController
|
7
7
|
def index
|
8
8
|
@search_query = params[:q] || params[:account_id]
|
9
|
-
|
9
|
+
@advance_search_query = request.query_string
|
10
10
|
@ordering = params[:ordering] || (@search_query.blank? ? 'desc' : 'asc')
|
11
11
|
@offset = params[:offset] || 0
|
12
12
|
@limit = params[:limit] || 50
|
13
|
+
@search_fields = Kaui::Payment::ADVANCED_SEARCH_COLUMNS.map { |attr| [attr, attr.split('_').join(' ').capitalize] }
|
13
14
|
|
14
15
|
@max_nb_records = @search_query.blank? ? Kaui::Payment.list_or_search(nil, 0, 0, options_for_klient).pagination_max_nb_records : 0
|
15
16
|
end
|
@@ -19,25 +20,34 @@ module Kaui
|
|
19
20
|
start_date = params[:startDate]
|
20
21
|
end_date = params[:endDate]
|
21
22
|
all_fields_checked = params[:allFieldsChecked] == 'true'
|
23
|
+
query_string = params[:search]
|
24
|
+
|
22
25
|
if all_fields_checked
|
23
26
|
columns = KillBillClient::Model::PaymentAttributes.instance_variable_get('@json_attributes') - %w[transactions audit_logs]
|
27
|
+
csv_headers = columns.dup
|
28
|
+
Kaui::Payment::REMAPPING_FIELDS.each do |k, v|
|
29
|
+
index = csv_headers.index(k)
|
30
|
+
csv_headers[index] = v if index
|
31
|
+
end
|
24
32
|
else
|
25
33
|
columns = params.require(:columnsString).split(',').map { |attr| attr.split.join('_').downcase }
|
34
|
+
csv_headers = columns.dup
|
26
35
|
Kaui::Payment::REMAPPING_FIELDS.each do |k, v|
|
27
36
|
index = columns.index(v)
|
28
37
|
columns[index] = k if index
|
29
38
|
end
|
30
39
|
end
|
31
|
-
|
40
|
+
query_string = remapping_addvanced_search_fields(query_string, Kaui::Payment::ADVANCED_SEARCH_NAME_CHANGES)
|
32
41
|
kb_params = {}
|
33
42
|
kb_params[:startDate] = Date.parse(start_date).strftime('%Y-%m-%d') if start_date
|
34
43
|
kb_params[:endDate] = Date.parse(end_date).strftime('%Y-%m-%d') if end_date
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
44
|
+
account = account_id.present? ? Kaui::Account.find_by_id_or_key(account_id, false, false, options_for_klient) : nil
|
45
|
+
|
46
|
+
payments = if account_id.present? && query_string.blank?
|
47
|
+
Kaui::Account.paginated_payments(account_id, nil, nil, 'NONE', options_for_klient).map! { |payment| Kaui::Payment.build_from_raw_invoice(payment) }
|
48
|
+
else
|
49
|
+
Kaui::Payment.list_or_search(query_string, 0, MAXIMUM_NUMBER_OF_RECORDS_DOWNLOAD, options_for_klient.merge(params: kb_params))
|
50
|
+
end
|
41
51
|
|
42
52
|
payments.each do |payment|
|
43
53
|
created_date = nil
|
@@ -99,6 +109,7 @@ module Kaui
|
|
99
109
|
end
|
100
110
|
|
101
111
|
payments = if account.nil?
|
112
|
+
search_key = remapping_addvanced_search_fields(search_key, Kaui::Payment::ADVANCED_SEARCH_NAME_CHANGES)
|
102
113
|
Kaui::Payment.list_or_search(search_key, offset, limit, options_for_klient)
|
103
114
|
else
|
104
115
|
account.payments(options_for_klient).map! { |payment| Kaui::Payment.build_from_raw_payment(payment) }
|
@@ -12,6 +12,8 @@ module Kaui
|
|
12
12
|
# The sign-in flow eventually calls authenticate! from config/initializers/killbill_authenticatable.rb
|
13
13
|
|
14
14
|
rescue_from(StandardError) do |exception|
|
15
|
+
Rails.logger.error(exception.message)
|
16
|
+
Rails.logger.error(exception.backtrace.join("\n")) if exception.backtrace
|
15
17
|
@error = standardize_exception(exception)
|
16
18
|
render 'kaui/errors/500', status: 500, layout: false
|
17
19
|
end
|
@@ -5,8 +5,10 @@ module Kaui
|
|
5
5
|
def standardize_exception(exception)
|
6
6
|
if defined?(JRUBY_VERSION)
|
7
7
|
case exception
|
8
|
-
when ActiveRecord::JDBCError
|
8
|
+
when ActiveRecord::JDBCError, ActiveRecord::NoDatabaseError, ActiveRecord::DatabaseConnectionError, ActiveRecord::ConnectionNotEstablished
|
9
9
|
return I18n.translate('errors.messages.unable_to_connect_database')
|
10
|
+
else
|
11
|
+
return exception.message
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
data/app/models/kaui/account.rb
CHANGED
@@ -7,12 +7,15 @@ module Kaui
|
|
7
7
|
SENSIVITE_DATA_FIELDS = %w[name email].freeze
|
8
8
|
REMAPPING_FIELDS = {
|
9
9
|
'is_payment_delegated_to_parent' => 'pay_via_parent',
|
10
|
-
'bill_cycle_day_local' => 'bcd',
|
11
10
|
'account_balance' => 'balance',
|
11
|
+
'bill_cycle_day_local' => 'bcd',
|
12
12
|
'account_cba' => 'cba',
|
13
13
|
'is_migrated' => 'migrated'
|
14
14
|
}.freeze
|
15
15
|
|
16
|
+
ADVANCED_SEARCH_COLUMNS = %w[id external_key email name currency parent_account_id pay_via_parent payment_method_id time_zone country postal_code].freeze
|
17
|
+
ADVANCED_SEARCH_NAME_CHANGES = [%w[pay_via_parent is_payment_delegated_to_parent]].freeze
|
18
|
+
|
16
19
|
def check_account_details_phone
|
17
20
|
return true if phone =~ /\A(?:\+?\d{1,3}\s*-?)?\(?(?:\d{3})?\)?[- ]?\d{3}[- ]?\d{4}\z/i
|
18
21
|
|
data/app/models/kaui/invoice.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
module Kaui
|
4
4
|
class Invoice < KillBillClient::Model::Invoice
|
5
5
|
TABLE_IGNORE_COLUMNS = %w[amount balance credit_adj refund_adj items is_parent_invoice parent_invoice_id parent_account_id audit_logs bundle_keys].freeze
|
6
|
+
ADVANCED_SEARCH_COLUMNS = %w[id account_id invoice_date target_date currency status balance].freeze
|
7
|
+
ADVANCED_SEARCH_NAME_CHANGES = [%w[ac_id account_id]].freeze
|
6
8
|
|
7
9
|
def self.build_from_raw_invoice(raw_invoice)
|
8
10
|
result = Kaui::Invoice.new
|
data/app/models/kaui/payment.rb
CHANGED
@@ -14,6 +14,8 @@ module Kaui
|
|
14
14
|
'credited_amount' => 'credit',
|
15
15
|
'refunded_amount' => 'refund'
|
16
16
|
}.freeze
|
17
|
+
ADVANCED_SEARCH_COLUMNS = %w[id account_id payment_method_id external_key].freeze
|
18
|
+
ADVANCED_SEARCH_NAME_CHANGES = [%w[ac_id account_id]].freeze
|
17
19
|
|
18
20
|
def self.build_from_raw_payment(raw_payment)
|
19
21
|
result = Kaui::Payment.new
|
@@ -0,0 +1,189 @@
|
|
1
|
+
<div class="modal fade" id="advanceSearchModal" tabindex="-1" role="dialog" aria-labelledby="advanceSearchModalLabel" aria-hidden="true">
|
2
|
+
<div class="modal-dialog" role="document">
|
3
|
+
<div class="modal-content">
|
4
|
+
<div class="modal-header">
|
5
|
+
<h5 class="modal-title" id="advanceSearchModalLabel">Advance Search</h5>
|
6
|
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
7
|
+
<span aria-hidden="true">×</span>
|
8
|
+
</button>
|
9
|
+
</div>
|
10
|
+
<div class="modal-body">
|
11
|
+
<form id="advanceSearchForm">
|
12
|
+
<div class="form-group d-flex align-items-center">
|
13
|
+
<label for="searchFieldSelect" class="mr-2" style="width: 30%;">Search Fields:</label>
|
14
|
+
<select id="searchFieldSelect" class="form-control mr-2">
|
15
|
+
<% @search_fields.each do |value, title| %>
|
16
|
+
<option value="<%= value %>"><%= title %></option>
|
17
|
+
<% end %>
|
18
|
+
</select>
|
19
|
+
<button type="button" class="btn btn-secondary" id="addSearchField">Add</button>
|
20
|
+
</div>
|
21
|
+
<div id="search-fields-container">
|
22
|
+
</div>
|
23
|
+
</form>
|
24
|
+
</div>
|
25
|
+
<div class="modal-footer">
|
26
|
+
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
27
|
+
<button type="button" class="btn btn-primary" id="applyAdvanceSearch">Apply Search</button>
|
28
|
+
<button type="button" class="btn btn-danger" id="clearAdvanceSearch">Clear Search</button>
|
29
|
+
</div>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<template id="search-field-template">
|
35
|
+
<div class="form-group row align-items-center search-field">
|
36
|
+
<label class="col-sm-4 col-form-label search-field-label"></label>
|
37
|
+
<div class="col-sm-3">
|
38
|
+
<select class="form-control search-field-filter">
|
39
|
+
<option value="eq">Equals</option>
|
40
|
+
<option value="neq">Not Equals</option>
|
41
|
+
<option value="gt">Greater Than</option>
|
42
|
+
<option value="gte">Greater Than Or Equal</option>
|
43
|
+
<option value="lt">Less Than</option>
|
44
|
+
<option value="lte">Less Than Or Equal</option>
|
45
|
+
<option value="like">Like</option>
|
46
|
+
</select>
|
47
|
+
</div>
|
48
|
+
<div class="col-sm-4">
|
49
|
+
<input type="text" class="form-control search-field-value">
|
50
|
+
</div>
|
51
|
+
<div class="col-sm-1">
|
52
|
+
<i class="glyphicon glyphicon-remove" id=remove-search-field></i>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
</template>
|
56
|
+
|
57
|
+
<style>
|
58
|
+
.form-group.row.align-items-center {
|
59
|
+
display: flex;
|
60
|
+
align-items: center;
|
61
|
+
}
|
62
|
+
|
63
|
+
.form-group.row.align-items-center label {
|
64
|
+
margin-bottom: 0; /* Remove default margin */
|
65
|
+
}
|
66
|
+
|
67
|
+
.form-group.row.align-items-center .form-control {
|
68
|
+
margin-right: 10px; /* Add some space between elements */
|
69
|
+
}
|
70
|
+
|
71
|
+
.form-group.d-flex {
|
72
|
+
display: flex;
|
73
|
+
align-items: center;
|
74
|
+
}
|
75
|
+
|
76
|
+
.form-group.d-flex label {
|
77
|
+
margin-bottom: 0; /* Remove default margin */
|
78
|
+
}
|
79
|
+
|
80
|
+
.form-group.d-flex .form-control {
|
81
|
+
margin-right: 10px; /* Add some space between the select box and the button */
|
82
|
+
}
|
83
|
+
|
84
|
+
#search-labels-container .label {
|
85
|
+
margin-left: 5px; /* Add space between labels */
|
86
|
+
margin-bottom: 5px; /* Add space below labels if they wrap to the next line */
|
87
|
+
color: white;
|
88
|
+
}
|
89
|
+
|
90
|
+
.filter-bar-container {
|
91
|
+
display: flex;
|
92
|
+
justify-content: flex-start; /* Align items to the left */
|
93
|
+
align-items: center; /* Center items vertically */
|
94
|
+
}
|
95
|
+
|
96
|
+
.filter-bar {
|
97
|
+
display: flex;
|
98
|
+
align-items: center; /* Center items vertically */
|
99
|
+
}
|
100
|
+
|
101
|
+
.filter-bar label {
|
102
|
+
margin: 10px; /* Add some space between the label and the select box */
|
103
|
+
}
|
104
|
+
</style>
|
105
|
+
|
106
|
+
<%= javascript_tag do %>
|
107
|
+
$(document).ready(function() {
|
108
|
+
populateSearchLabelsFromUrl();
|
109
|
+
var dateFields = ['Created date', 'Updated date', 'Reference time'];
|
110
|
+
// Handle the "Add" button click to add new search fields
|
111
|
+
$('#addSearchField').on('click', function() {
|
112
|
+
var selectedField = $('#searchFieldSelect option:selected').text();
|
113
|
+
var template = document.getElementById('search-field-template').content.cloneNode(true);
|
114
|
+
|
115
|
+
// Set the label and input names based on the selected field
|
116
|
+
template.querySelector('.search-field-label').textContent = selectedField.replace(/([A-Z])/g, ' $1').trim();
|
117
|
+
template.querySelector('.search-field-filter').name = selectedField + 'Filter';
|
118
|
+
|
119
|
+
// Check if the field should use a date input
|
120
|
+
if (dateFields.includes(selectedField)) {
|
121
|
+
template.querySelector('.search-field-value').type = 'date';
|
122
|
+
} else {
|
123
|
+
template.querySelector('.search-field-value').type = 'text';
|
124
|
+
}
|
125
|
+
template.querySelector('.search-field-value').name = selectedField;
|
126
|
+
|
127
|
+
// Append the new search field to the container
|
128
|
+
document.getElementById('search-fields-container').appendChild(template);
|
129
|
+
});
|
130
|
+
|
131
|
+
// Handle the "Apply Search" button click inside the modal
|
132
|
+
$('#applyAdvanceSearch').on('click', function() {
|
133
|
+
var searchFields = $('.search-field');
|
134
|
+
var searchLabelsContainer = $('#search-labels-container');
|
135
|
+
searchLabelsContainer.empty();
|
136
|
+
|
137
|
+
var table = $('#accounts-table').DataTable();
|
138
|
+
table.on('preXhr.dt', function(e, settings, data) {
|
139
|
+
data.search.value = searchQuery;
|
140
|
+
});
|
141
|
+
|
142
|
+
table.ajax.url("<%= accounts_pagination_path(:ordering => @ordering, :format => :json) %>").load();
|
143
|
+
|
144
|
+
// Update the URL with the search parameters
|
145
|
+
var searchParams = searchQuery('');
|
146
|
+
if (searchParams) {
|
147
|
+
var newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + searchParams;
|
148
|
+
window.history.pushState({ path: newUrl }, '', newUrl);
|
149
|
+
}
|
150
|
+
|
151
|
+
searchFields.each(function() {
|
152
|
+
var filter = $(this).find('.search-field-filter option:selected').text();
|
153
|
+
var value = $(this).find('.search-field-value').val();
|
154
|
+
var columnName = $(this).find('.search-field-filter').attr('name').replace('Filter', '');
|
155
|
+
|
156
|
+
// Create and append the search label
|
157
|
+
if (value !== '') {
|
158
|
+
var label = $('<span>', {
|
159
|
+
class: 'label label-info',
|
160
|
+
text: columnName + ' [' + filter + '] ' + value
|
161
|
+
});
|
162
|
+
}
|
163
|
+
searchLabelsContainer.append(label);
|
164
|
+
});
|
165
|
+
|
166
|
+
$('#advanceSearchModal').modal('hide');
|
167
|
+
});
|
168
|
+
|
169
|
+
// Populate the modal with the current filters when it is shown
|
170
|
+
$('#advanceSearchModal').on('show.bs.modal', function() {
|
171
|
+
showAdvanceSearchModal();
|
172
|
+
$('#search-fields-container .search-field').each(function() {
|
173
|
+
var input = $(this).find('.search-field-value');
|
174
|
+
if (dateFields.includes(input.attr('name'))) {
|
175
|
+
input.attr('type', 'date');
|
176
|
+
}
|
177
|
+
});
|
178
|
+
});
|
179
|
+
|
180
|
+
$('#clearAdvanceSearch').on('click', function() {
|
181
|
+
clearAdvanceSearch();
|
182
|
+
});
|
183
|
+
|
184
|
+
// Handle the remove icon click event to remove search fields
|
185
|
+
$('#search-fields-container').on('click', '#remove-search-field', function() {
|
186
|
+
$(this).closest('.search-field').remove();
|
187
|
+
});
|
188
|
+
});
|
189
|
+
<% end %>
|