add workflow for adding products/stock through barcodes
This commit is contained in:
parent
bfe86ae481
commit
19dec68c59
16 changed files with 115 additions and 66 deletions
21
app/assets/javascripts/increment.js
Normal file
21
app/assets/javascripts/increment.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
ready = function() {
|
||||
parseIntNaN = function(value) {
|
||||
parsed_value = parseInt(value);
|
||||
if (isNaN(parsed_value)) {
|
||||
return 0;
|
||||
} else {
|
||||
return parsed_value;
|
||||
}
|
||||
}
|
||||
|
||||
increment_function = function() {
|
||||
target = $(this).data("target");
|
||||
$(target).val(parseIntNaN($(target).data("default")) + parseIntNaN($(this).val()));
|
||||
}
|
||||
|
||||
$('[data-increment]').change(increment_function);
|
||||
$('[data-increment]').keyup(increment_function);
|
||||
}
|
||||
|
||||
$(document).ready(ready);
|
||||
$(document).on('page:load', ready);
|
|
@ -18,7 +18,10 @@
|
|||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
.col-md-2 {
|
||||
}
|
||||
|
||||
#product_buttons {
|
||||
.col-md-2, .col-md-3 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
button.product {
|
||||
|
|
15
app/controllers/barcodes_controller.rb
Normal file
15
app/controllers/barcodes_controller.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
class BarcodesController < ApplicationController
|
||||
load_resource :product
|
||||
load_and_authorize_resource :barcode, through: :product
|
||||
|
||||
def create
|
||||
@barcode.save
|
||||
redirect_to barcode_products_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def barcode_params
|
||||
params.require(:barcode).permit(:code)
|
||||
end
|
||||
end
|
|
@ -3,15 +3,26 @@ class ProductsController < ApplicationController
|
|||
|
||||
respond_to :html, :js
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
def create
|
||||
if @product.save
|
||||
flash[:success] = "Product created!"
|
||||
redirect_to products_path
|
||||
redirect_to barcode_products_path
|
||||
else
|
||||
render 'new'
|
||||
render 'link'
|
||||
end
|
||||
end
|
||||
|
||||
def barcode
|
||||
end
|
||||
|
||||
def load_barcode
|
||||
@product = Barcode.find_by(code: params[:barcode]).try(:product)
|
||||
if @product
|
||||
render 'products/stock_entry'
|
||||
else
|
||||
@product = Product.new
|
||||
@product.barcodes.build(code: params[:barcode])
|
||||
render 'products/link'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -28,7 +39,10 @@ class ProductsController < ApplicationController
|
|||
|
||||
def update
|
||||
@product.update_attributes product_params
|
||||
respond_with @product
|
||||
respond_to do |format|
|
||||
format.js { respond_with @product }
|
||||
format.html { redirect_to barcode_products_path }
|
||||
end
|
||||
end
|
||||
|
||||
def from_barcode
|
||||
|
@ -38,6 +52,6 @@ class ProductsController < ApplicationController
|
|||
private
|
||||
|
||||
def product_params
|
||||
params.require(:product).permit(:name, :price, :avatar, :category, :stock, :calories, :deleted, :barcode)
|
||||
params.require(:product).permit(:name, :price, :avatar, :category, :stock, :calories, :deleted, :barcode, barcodes_attributes: [:code])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
class StocksController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
|
||||
def new
|
||||
Product.all.each do |p|
|
||||
@stock.stock_entries << Stock::StockEntry.new(product: p)
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@stock = Stock.new(params[:stock])
|
||||
if @stock.update
|
||||
flash[:success] = "Stock updated!"
|
||||
redirect_to products_path
|
||||
else
|
||||
render 'new'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -12,6 +12,6 @@
|
|||
class Barcode < ActiveRecord::Base
|
||||
belongs_to :product
|
||||
|
||||
validates :product, presence: true
|
||||
validates :code, uniqueness: true
|
||||
# validates :product, presence: true
|
||||
validates :code, presence: true, uniqueness: true
|
||||
end
|
||||
|
|
|
@ -22,6 +22,7 @@ class Product < ActiveRecord::Base
|
|||
|
||||
has_many :order_items
|
||||
has_many :barcodes
|
||||
accepts_nested_attributes_for :barcodes
|
||||
|
||||
enum category: %w(food beverages other)
|
||||
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
%span.caret
|
||||
%ul.dropdown-menu{role: "menu"}
|
||||
%li= link_to "List", products_path
|
||||
%li= link_to "Add product" , new_product_path
|
||||
%li= link_to "Add stock", new_stock_path
|
||||
%li= link_to "Add product" , barcode_products_path
|
||||
%li.dropdown
|
||||
%a.dropdown-toggle{"data-toggle" => "dropdown", href: "#"}
|
||||
Logged in as #{current_user.name}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
.col-xs-3.pull-right
|
||||
%input#product_search.form-control{ placeholder: "Search" }
|
||||
.modal-body
|
||||
.container-fluid
|
||||
#product_buttons.container-fluid
|
||||
- @products.each do |product|
|
||||
.col-md-2{ data: { name: product.name } }
|
||||
%button.btn.btn-default.product{ data: { product: product.id, dismiss: :modal } }
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
.row
|
||||
.col-md-6.col-md-offset-3.sign-in
|
||||
= f_form_for @product, html: { multipart: true } do |f|
|
||||
= f.error_messages
|
||||
= f.text_field :name
|
||||
= f.price_field :price
|
||||
= f.collection_select :category, Product.categories.keys
|
||||
= f.number_field :stock
|
||||
= f.number_field :calories
|
||||
= f.file_field :avatar
|
||||
= f.submit
|
||||
= f_form_for @product, html: { multipart: true } do |f|
|
||||
= f.error_messages
|
||||
= f.text_field :name
|
||||
= f.price_field :price
|
||||
= f.collection_select :category, Product.categories.keys
|
||||
= f.number_field :stock
|
||||
= f.number_field :calories
|
||||
= f.file_field :avatar
|
||||
= f.fields_for :barcodes do |ff|
|
||||
= ff.number_field :code, readonly: true
|
||||
= f.submit
|
||||
|
|
6
app/views/products/barcode.html.haml
Normal file
6
app/views/products/barcode.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
|||
.row
|
||||
.col-md-6.col-md-offset-3.center
|
||||
%h2 Scan barcode
|
||||
= form_tag load_barcode_products_path do
|
||||
.barcode-wrapper
|
||||
%input.center-block{ type: :number, name: :barcode, autofocus: true }
|
12
app/views/products/link.html.haml
Normal file
12
app/views/products/link.html.haml
Normal file
|
@ -0,0 +1,12 @@
|
|||
.row
|
||||
.col-md-7
|
||||
%h4.pull-right Select a product to link the barcode to an existing product ...
|
||||
#product_buttons.row
|
||||
- Product.all.each do |product|
|
||||
.col-md-3
|
||||
= button_to product_barcodes_path(product), class: "btn btn-default product", data: { product: product.id, dismiss: :modal }, params: { "barcode[code]" => params[:barcode] } do
|
||||
%p= product.name
|
||||
= image_tag product.avatar(:dagschotel), class: "center"
|
||||
.col-md-5
|
||||
%h4 or create a new one
|
||||
= render 'products/form'
|
16
app/views/products/stock_entry.html.haml
Normal file
16
app/views/products/stock_entry.html.haml
Normal file
|
@ -0,0 +1,16 @@
|
|||
.row
|
||||
.col-md-6.col-md-offset-3
|
||||
= form_for @product do |f|
|
||||
%table
|
||||
%tr
|
||||
%td Current stock
|
||||
%td= @product.stock
|
||||
%tr
|
||||
%td Purchase
|
||||
%td
|
||||
%input.form-control.new_stock{ type: :number, data: { increment: true, target: "#product_stock" }}
|
||||
%tr
|
||||
%td New stock
|
||||
%td= f.number_field :stock, data:{ default: f.object.stock }, class: "form-control"
|
||||
%tr
|
||||
%td= f.submit "Update stock"
|
|
@ -1,8 +0,0 @@
|
|||
- unless @stock.valid?
|
||||
.panel.panel-danger.form-errors
|
||||
.panel-heading
|
||||
= "#{pluralize(@stock.errors.count + @stock.stock_entries.map(&:errors).map(&:count).sum, "error")} prohibited this stock from being saved:"
|
||||
.panel-body
|
||||
%ul
|
||||
= @stock.errors.full_messages.map{ |m| content_tag(:li, m) }.join.html_safe
|
||||
= @stock.stock_entries.map{ |se| se.errors.full_messages.map{ |e| "#{se.product.name}: #{e}" } }.flatten.map{ |m| content_tag(:li, m) }.join.html_safe
|
|
@ -1,13 +0,0 @@
|
|||
= content_for :title, "Add stock"
|
||||
.row
|
||||
.col-md-6.col-md-offset-3
|
||||
= f_form_for @stock do |f|
|
||||
= render 'stocks/errors'
|
||||
= f.fields_for :stock_entries do |se_field|
|
||||
.row
|
||||
.col-sm-3
|
||||
= image_tag se_field.object.product.avatar
|
||||
.col-sm-9
|
||||
= se_field.hidden_field :product_id
|
||||
= se_field.number_field :count, skip_label: true
|
||||
= f.submit "Insert stock", class: 'btn btn-primary'
|
|
@ -26,11 +26,13 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
resources :products, only: [:new, :create, :index, :edit, :update] do
|
||||
resources :barcodes, only: :create
|
||||
collection do
|
||||
post 'barcode' => 'products#from_barcode', as: :from_barcode
|
||||
post 'from_barcode' => 'products#from_barcode', as: :from_barcode
|
||||
get 'barcode' => 'products#barcode', as: :barcode
|
||||
post 'barcode' => 'products#load_barcode', as: :load_barcode
|
||||
end
|
||||
end
|
||||
resources :stocks, only: [:new, :create]
|
||||
|
||||
get 'overview' => 'orders#overview', as: "orders"
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue