Skip to content

Commit

Permalink
Merge pull request #371 from hmnhf/feature/#366/search-invoice-by-number
Browse files Browse the repository at this point in the history
#366 Allow searching invoices by number
  • Loading branch information
pierre authored Jul 31, 2023
2 parents 367aade + 1ca7f75 commit ae2e8ac
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 14 deletions.
33 changes: 21 additions & 12 deletions app/controllers/kaui/home_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,23 @@ def account_search(search_query, search_by = nil, fast = 0, options = {})
end

def invoice_search(search_query, search_by = nil, fast = 0, options = {})
if search_by == 'ID'
case search_by
when 'ID'
begin
invoice = Kaui::Invoice.find_by_id(search_query, 'NONE', options)
redirect_to account_invoice_path(invoice.account_id, invoice.invoice_id) and return
rescue KillBillClient::API::NotFound => _e
search_error("No invoice matches \"#{search_query}\"")
end
elsif search_by == 'EXTERNAL_KEY'
unsupported_external_key_search('INVOICE')
when 'EXTERNAL_KEY'
unsupported_search_field('INVOICE', search_by)
when 'NUMBER'
begin
invoice = Kaui::Invoice.find_by_number(search_query, 'NONE', options)
redirect_to account_invoice_path(invoice.account_id, invoice.invoice_id) and return
rescue KillBillClient::API::NotFound, KillBillClient::API::BadRequest => _e
search_error("No invoice matches \"#{search_query}\"")
end
else
invoice = Kaui::Invoice.list_or_search(search_query, 0, 1, options).first
if invoice.blank?
Expand Down Expand Up @@ -157,7 +165,7 @@ def credit_search(search_query, search_by = nil, _fast = 0, options = {})
search_error("No credit matches \"#{search_query}\"")
end
else
unsupported_external_key_search('CREDIT')
unsupported_search_field('CREDIT', search_by)
end
end

Expand All @@ -170,7 +178,7 @@ def custom_field_search(search_query, search_by = nil, fast = 0, options = {})
redirect_to custom_fields_path(q: search_query, fast:)
end
else
unsupported_external_key_search('CUSTOM FIELD')
unsupported_search_field('CUSTOM FIELD', search_by)
end
end

Expand All @@ -183,7 +191,7 @@ def invoice_payment_search(search_query, search_by = nil, _fast = 0, options = {
search_error("No invoice payment matches \"#{search_query}\"")
end
else
unsupported_external_key_search('INVOICE PAYMENT')
unsupported_search_field('INVOICE PAYMENT', search_by)
end
end

Expand All @@ -196,7 +204,7 @@ def subscription_search(search_query, search_by = nil, _fast = 0, options = {})
search_error("No subscription matches \"#{search_query}\"")
end
else
unsupported_external_key_search('SUBSCRIPTION')
unsupported_search_field('SUBSCRIPTION', search_by)
end
end

Expand All @@ -209,7 +217,7 @@ def tag_search(search_query, search_by = nil, fast = 0, options = {})
redirect_to tags_path(q: search_query, fast:)
end
else
unsupported_external_key_search('TAG')
unsupported_search_field('TAG', search_by)
end
end

Expand All @@ -222,7 +230,7 @@ def tag_definition_search(search_query, search_by = nil, fast = 0, options = {})
search_error("No tag definition matches \"#{search_query}\"")
end
elsif search_by == 'EXTERNAL_KEY'
unsupported_external_key_search('TAG DEFINITION')
unsupported_search_field('TAG DEFINITION', search_by)
else
tag_definition = Kaui::TagDefinition.find_by_name(search_query, 'NONE', options)
if tag_definition.blank?
Expand All @@ -238,8 +246,9 @@ def tag_definition_search(search_query, search_by = nil, fast = 0, options = {})
end
end

def unsupported_external_key_search(object_type)
search_error("\"#{object_type}\": Search by \"EXTERNAL KEY\" is not supported.")
def unsupported_search_field(object_type, object_field)
field_name = object_field.gsub('_', ' ')
search_error("\"#{object_type}\": Search by \"#{field_name}\" is not supported.")
end

def search_error(message)
Expand Down Expand Up @@ -267,7 +276,7 @@ def parse_query(query)
'0'
end

search_error("\"#{search_by}\" is not a valid search by value") if !search_by.blank? && !%w[ID EXTERNAL_KEY].include?(search_by)
search_error("\"#{search_by}\" is not a valid search by value") if !search_by.blank? && !search_by.in?(Kaui::ObjectHelper::ADVANCED_SEARCH_OBJECT_FIELDS)

[object_type, search_for, search_by, fast]
end
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/kaui/invoices_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ def restful_show
redirect_to account_invoice_path(invoice.account_id, invoice.invoice_id)
end

def restful_show_by_number
invoice = Kaui::Invoice.find_by_number(params.require(:number), 'NONE', options_for_klient)
redirect_to account_invoice_path(invoice.account_id, invoice.invoice_id)
end

def show_html
render html: Kaui::Invoice.as_html(params.require(:id), options_for_klient).html_safe
end
Expand Down
17 changes: 16 additions & 1 deletion app/helpers/kaui/object_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

module Kaui
module ObjectHelper
ADVANCED_SEARCH_OBJECT_FIELDS = %w[ID EXTERNAL_KEY NUMBER].freeze
ADVANCED_SEARCH_OBJECT_FIELDS_MAP = {
# ID is supported by all object types, hence not listed.
EXTERNAL_KEY: %w[ACCOUNT PAYMENT TRANSACTION BUNDLE],
NUMBER: %w[INVOICE]
}.freeze

# Because we don't have access to the account_id, we use the restful_show routes
def url_for_object(object_id, object_type)
case object_type
Expand All @@ -27,7 +34,15 @@ def object_types
end

def object_types_for_advanced_search
%i[ACCOUNT BUNDLE INVOICE CREDIT CUSTOM_FIELD INVOICE_PAYMENT INVOICE PAYMENT SUBSCRIPTION TRANSACTION TAG TAG_DEFINITION]
%i[ACCOUNT BUNDLE INVOICE CREDIT CUSTOM_FIELD INVOICE_PAYMENT PAYMENT SUBSCRIPTION TRANSACTION TAG TAG_DEFINITION]
end

def object_fields_for_advanced_search
[' '] + ADVANCED_SEARCH_OBJECT_FIELDS
end

def advanced_search_object_fields_map
ADVANCED_SEARCH_OBJECT_FIELDS_MAP
end
end
end
23 changes: 22 additions & 1 deletion app/views/kaui/home/_advanced_search_modal.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<div class="form-group">
<%= label_tag :search_by, 'Search by', :class => 'col-sm-4 control-label' %>
<div class="col-sm-8">
<%= select_tag :search_by, options_for_select(['', 'ID', 'EXTERNAL_KEY'],''), :class => 'form-control' %>
<%= select_tag :search_by, options_for_select(object_fields_for_advanced_search,''), :class => 'form-control' %>
</div>
</div>
<div class="form-group">
Expand Down Expand Up @@ -68,13 +68,34 @@
$('#advancedQuery').val(query);
}

const searchByFieldsMap = <%= advanced_search_object_fields_map.to_json.html_safe %>;
function refresh_search_by() {
var objectType = $('#object_type').val();

// Clears the selected field if it's not supported by the selected object type
var searchBy = $('#search_by').val();
if (searchByFieldsMap[searchBy] && !searchByFieldsMap[searchBy].includes(objectType)) {
$('#search_by').val(' ');
refresh_query();
}

// Updates search options to only show fields supported by the selected object type
for (field in searchByFieldsMap) {
var isSupported = searchByFieldsMap[field].includes(objectType);
var fieldOption = $(`#search_by > option[value=${field}]`);
isSupported ? fieldOption.show() : fieldOption.hide();
}
}

$('#search_for').keyup(function(){ refresh_query(); });
$('#search_for').change(function(){ refresh_query(); });
$('#object_type').change(function(){ refresh_query(); });
$('#object_type').change(function(){ refresh_search_by(); });
$('#search_by').change(function(){ refresh_query(); });
$('#fast').change(function(){ refresh_query(); });

refresh_query();
refresh_search_by();

});
<% end %>
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def nested_param
scope '/invoices' do
match '/pagination' => 'invoices#pagination', :via => :get, :as => 'invoices_pagination'
match '/:id/show_html' => 'invoices#show_html', :via => :get, :as => 'show_html_invoice'
match '/:number' => 'invoices#restful_show_by_number', :via => :get, :constraints => { number: /\d+/ }
match '/:id' => 'invoices#restful_show', :via => :get, :as => 'invoice'
match '/commit' => 'invoices#commit_invoice', :via => :post, :as => 'commit_invoice'
match '/void' => 'invoices#void_invoice', :via => :delete, :as => 'void_invoice'
Expand Down
2 changes: 2 additions & 0 deletions lib/kaui.rb
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,11 @@ def self.config

# ruby-1.8 compatibility
module Kernel
# rubocop:disable Style/ArgumentsForwarding
def define_singleton_method(*args, &)
class << self
self
end.send(:define_method, *args, &)
end
# rubocop:enable Style/ArgumentsForwarding
end
9 changes: 9 additions & 0 deletions test/functional/kaui/home_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ class HomeControllerTest < Kaui::FunctionalTestHelper
assert_redirected_to home_path
assert_equal '"INVOICE": Search by "EXTERNAL KEY" is not supported.', flash[:error]

# search by number
get :search, params: { q: query_builder('INVOICE', @bundle_invoice.invoice_number, 'NUMBER') }
assert_redirected_to account_invoice_path(@bundle_invoice.account_id, @bundle_invoice.invoice_id)

# search by number and fails
get :search, params: { q: query_builder('INVOICE', '112', 'NUMBER') }
assert_redirected_to home_path
assert_equal 'No invoice matches "112"', flash[:error]

# search by BLANK only first
get :search, params: { q: query_builder('INVOICE', @bundle_invoice.invoice_number, nil, '1') }
assert_redirected_to account_invoice_path(@bundle_invoice.account_id, @bundle_invoice.invoice_id)
Expand Down
5 changes: 5 additions & 0 deletions test/functional/kaui/invoices_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ class InvoicesControllerTest < Kaui::FunctionalTestHelper
assert_redirected_to account_invoice_path(@invoice_item.account_id, @invoice_item.invoice_id)
end

test 'should expose restful show by number endpoint' do
get :restful_show_by_number, params: { number: @bundle_invoice.invoice_number }
assert_redirected_to account_invoice_path(@bundle_invoice.account_id, @bundle_invoice.invoice_id)
end

test 'should render HTML invoice' do
get :show_html, params: { id: @invoice_item.invoice_id }
assert_response 200
Expand Down

0 comments on commit ae2e8ac

Please sign in to comment.