diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb
index 5679250..82548bd 100644
--- a/app/controllers/items_controller.rb
+++ b/app/controllers/items_controller.rb
@@ -12,11 +12,19 @@ class ItemsController < ApplicationController
before_action :require_login
def autocomplete
- term = params[:q].to_s
- items = Item.where("description LIKE ?", "%#{ActiveRecord::Base.sanitize_sql_like(term)}%").where(active: true).order(:description).limit(20)
+ term = ActiveRecord::Base.sanitize_sql_like(params[:q].to_s)
+ items = Item.where("description LIKE :t OR name LIKE :t OR sku LIKE :t", t: "%#{term}%")
+ .where(active: true)
+ .order(:description)
+ .limit(20)
render json: items.map { |i|
- { id: i.id, text: i.description, price: i.unit_price }
+ { id: i.id, name: i.name, sku: i.sku, description: i.description, price: i.unit_price }
}
end
+
+ def sync
+ Item.sync
+ redirect_to :home, flash: { notice: I18n.t(:label_syncing) }
+ end
end
\ No newline at end of file
diff --git a/app/services/item_sync_service.rb b/app/services/item_sync_service.rb
index da85c7d..23f894e 100644
--- a/app/services/item_sync_service.rb
+++ b/app/services/item_sync_service.rb
@@ -29,6 +29,8 @@ class ItemSyncService < SyncServiceBase
local.description = remote.description
local.unit_price = remote.unit_price
local.active = remote.active?
+ local.name = remote.name
+ local.sku = remote.sku
end
def log(msg)
diff --git a/app/views/line_items/_settings.html.erb b/app/views/line_items/_settings.html.erb
index 645a755..7ec7e56 100644
--- a/app/views/line_items/_settings.html.erb
+++ b/app/views/line_items/_settings.html.erb
@@ -2,4 +2,5 @@
<%=t(:label_item_count)%> <%= Item.count %> @ <%= Item.last_sync %>
<%=t(:label_last_sync)%> <%= Qbo.last_sync if Qbo.exists? %>
-
\ No newline at end of file
+
+<%= link_to t(:label_sync_now), items_sync_path%>
\ No newline at end of file
diff --git a/assets/javascripts/autocomplete.js b/assets/javascripts/autocomplete.js
index bb33f4d..d45a3b4 100644
--- a/assets/javascripts/autocomplete.js
+++ b/assets/javascripts/autocomplete.js
@@ -2,35 +2,45 @@
window.initLineItemAutocomplete = function(context) {
let scope = context || document;
+
$(scope).find(".line-item-description").each(function() {
if ($(this).data("autocomplete-initialized")) return;
$(this).data("autocomplete-initialized", true);
- $(this).autocomplete({
+ let ac = $(this).autocomplete({
appendTo: "body",
minLength: 2,
+
source: function(request, response) {
$.getJSON("/items/autocomplete", { q: request.term })
.done(function(data) {
+
response(data.map(function(item) {
return {
- label: item.text,
- value: item.text,
+ label: item.description,
+ value: item.description,
id: item.id,
+ name: item.name,
+ sku: item.sku,
+ description: item.description,
price: item.price || 0
};
}));
+
})
.fail(function(err){
console.error("Autocomplete error:", err);
response([]);
});
},
+
select: function(event, ui) {
let $input = $(this);
let row = $input.closest(".line-item");
- $input.val(ui.item.value); // <-- set description
+ // set description into input
+ $input.val(ui.item.description);
+
row.find(".item-id-field").val(ui.item.id);
if (ui.item.price !== undefined && row.find(".price-field").length) {
@@ -39,15 +49,31 @@
updateLineItemTotals();
- return false; // still prevent default to avoid double entry
+ return false;
},
+
change: function(event, ui) {
if (!ui.item) {
let row = $(this).closest(".line-item");
row.find(".item-id-field").val("");
}
}
+
});
+
+ // Custom rendering of autocomplete suggestions
+ ac.autocomplete("instance")._renderItem = function(ul, item) {
+ return $("