From 0bae1bcbed817ddea4c5c48e2ee0bfe8606cba39 Mon Sep 17 00:00:00 2001 From: Benjamin ter Kuile Date: Thu, 23 Aug 2012 18:50:06 +0200 Subject: [PATCH] end of day commit --- .gitignore | 1 + Gemfile.lock | 8 +- Models.dia | Bin 2735 -> 3530 bytes Models.dia~ | Bin 2645 -> 0 bytes app/assets/images/icons/order-check.png | Bin 0 -> 631 bytes app/assets/images/icons/order-check.svg | 458 ++++++++++++++++++ app/assets/images/icons/order-doublecheck.png | Bin 0 -> 1037 bytes app/assets/javascripts/application.js | 4 +- app/assets/javascripts/qrammer.js.coffee | 100 +++- app/assets/stylesheets/structure.css.sass | 33 ++ app/controllers/application_controller.rb | 25 +- app/controllers/dashboard_controller.rb | 29 +- app/controllers/lists_controller.rb | 34 ++ app/controllers/orders_controller.rb | 104 ++++ app/controllers/suppliers_controller.rb | 52 ++ app/helpers/application_helper.rb | 2 +- app/models/list.rb | 21 +- app/models/order.rb | 40 +- app/models/product_order.rb | 5 +- app/models/supplier.rb | 32 +- app/views/dashboard/home.html.slim | 4 +- app/views/dashboard/show_products.html.slim | 22 +- .../dashboard/view_active_list.html.slim | 37 ++ app/views/layouts/application.html.slim | 3 + app/views/orders/_form.html.slim | 14 + app/views/orders/edit.html.slim | 4 + app/views/orders/index.html.slim | 24 + app/views/orders/new.html.slim | 4 + app/views/orders/show.html.slim | 16 + app/views/suppliers/active_lists.html.slim | 15 + .../suppliers/active_order_list.html.slim | 16 + app/views/users/_form.html.slim | 21 +- app/views/users/index.html.slim | 52 +- app/views/users/show.html.slim | 23 +- config/locales/en.yml | 6 +- config/routes.rb | 16 +- stories | 15 + 37 files changed, 1157 insertions(+), 83 deletions(-) delete mode 100644 Models.dia~ create mode 100644 app/assets/images/icons/order-check.png create mode 100644 app/assets/images/icons/order-check.svg create mode 100644 app/assets/images/icons/order-doublecheck.png create mode 100644 app/assets/stylesheets/structure.css.sass create mode 100644 app/controllers/orders_controller.rb create mode 100644 app/views/dashboard/view_active_list.html.slim create mode 100644 app/views/orders/_form.html.slim create mode 100644 app/views/orders/edit.html.slim create mode 100644 app/views/orders/index.html.slim create mode 100644 app/views/orders/new.html.slim create mode 100644 app/views/orders/show.html.slim create mode 100644 app/views/suppliers/active_lists.html.slim create mode 100644 app/views/suppliers/active_order_list.html.slim diff --git a/.gitignore b/.gitignore index 06073069..64bcc76e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ /tmp .sass-cache/ *.swp +*~ db/xapian_db company_logo* public/assets diff --git a/Gemfile.lock b/Gemfile.lock index 0c32942e..d3788551 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -192,7 +192,7 @@ GEM tilt (~> 1.1, != 1.3.0) subexec (0.2.2) temple (0.4.0) - therubyracer (0.10.1) + therubyracer (0.10.2) libv8 (~> 3.3.10) thin (1.4.1) daemons (>= 1.0.9) @@ -203,11 +203,11 @@ GEM treetop (1.4.10) polyglot polyglot (>= 0.3.1) - twitter-bootstrap-rails (2.1.1) + twitter-bootstrap-rails (2.1.3) actionpack (>= 3.1) - less-rails (~> 2.2.2) + less-rails (~> 2.2.3) railties (>= 3.1) - therubyracer (= 0.10.1) + therubyracer (~> 0.10.2) tzinfo (0.3.33) uglifier (1.2.7) execjs (>= 0.3.0) diff --git a/Models.dia b/Models.dia index 42127149c4b336d0c10dbebf43de2f7f8c2d004d..c3269c3a92bff3bffa193f6e08e24cd5e4957477 100644 GIT binary patch literal 3530 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 literal 2735 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 diff --git a/app/assets/images/icons/order-check.png b/app/assets/images/icons/order-check.png new file mode 100644 index 0000000000000000000000000000000000000000..719338ebeb7de34c07b0735eea3768f638184fb8 GIT binary patch literal 631 zcmV--0*L*IP)>p@3>8XjbSNU7GDI?E6bHK~k`BcoZwv&)A(LRDwXifCU)P00qzUejL0%2(x*h!kxm4Xf(R& zb02{G&Jhrg+DFf8mD=|+VT2HAd3AX=90{-Z+!q-D0=7T3pKX`7*8wJGX501+%d*%c zv~+W+rs>*>&wUv25sdfm@gFpX*|vSxFpRgMQ0QGEkq8JVm&?6Wuc&!}_}mBX zaXkEdSl+4ZtdAXxh>*=@@9DZ;VT?(XQWy*dA6(bHrfJ%)VHme4r9c@K1IJFMQ{H>E zw{c<|rfFV^L?T^9Q7%wQLDXiovhzQAK($RJOwJggr zr4$%rFoA$1N!aanx9au!qnQ^a-kAUuMUkgLy0rmU+ zC(UN_@oCTrY!VbutJV511OPDgM@XmBj^j8#Ez8=R>nEAD5s$|g=7A6qegOomP+XaM RJLmua002ovPDHLkV1liS4^998 literal 0 HcmV?d00001 diff --git a/app/assets/images/icons/order-check.svg b/app/assets/images/icons/order-check.svg new file mode 100644 index 00000000..6bd8ed99 --- /dev/null +++ b/app/assets/images/icons/order-check.svg @@ -0,0 +1,458 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/assets/images/icons/order-doublecheck.png b/app/assets/images/icons/order-doublecheck.png new file mode 100644 index 0000000000000000000000000000000000000000..c69f078e2940a956d9b6e6588831273cc969474b GIT binary patch literal 1037 zcmV+o1oHcdP)Kaj=fl1>s0QG-eq z>1+o{Va^|+Y%R5dtIpBUjc&t-vVRYKu!Di%Hk;DHvV{&xr4OTmP;5FWK1>K9qn4VV zNe#&6GWIk1-9LMfgv>gpy>K4xIp2Ff=bn4H2RP^OJmw$t8wLjl4ZCTE-W@U*&voz| zLzd-|wwAVqhPH+US(Zz7(p(t7Fz)H{ERS9q_2+&2hRL#AVsEuCR8&?pnyO5VExj!d ze8av&#hUXM&wpfZvR}p+A9S_3ei*ql^4h*(KA-Q9<%s1$g{k6Ys!^aCg(`EE!|ib2 zLI@!MfOGGh`@nw0{wXCC5siSL6C_uwD}46-vxoN#^Lo8{+bgz+$z*a+jRMgK5RJgb z9~+tEa`HpYIX^vg`n`t6hA$|gD4z_~D8!fI)6-X`lXx#6+XCHSyWR=rd*P>FGIetva0zgOX8 zy}iBT7K`O_X=&*#gwX4pbLMut4|u)ad&U=x%~Ye1&to&Ysm5Zlr-D%4ROwSo`E>$(B0kraZOFlCm3UdF@|(HeN$1CKz)7vJ+s-| ziZKQO3xGuolu>xH{A44!nsn>+`fjV$Iw^{xfH4N)z?LSVB)-2kb?sC!2mk;%ozBBn ztM#!YNunSKfH4L^5I|McwX(9Z%3>d544$q%1^q!iC> zkw_${D9YQKrcp{MY`1JSn~g@JZ>g%9V2nKzr<8)CD7SY5{p&T(&(D98NF>GxAq5~~ z46@m5E*_5uW@l%=OQlktOeT{ohA_rpb#?VlI2=B?8>mpm;?ddJIaXa=J%KUSA%wJ* zm6cO-b93Q*-05__SXWo~&|olBVT@sYef{T|nVIAN2Lb@t@we{i=(spAFtFLx)g|u~ zcez}3e!qXMudnYe0O + table = $('#active-order-table') + tbody = table.find('tbody') + tbody = $('').appendTo(table) unless tbody.length + tbody.find('tr').remove() + total = 0.0 + for product_id, info of window.active_list + total += info.product.price * info.number + row = $('').attr('id', 'active-order-row-'+product_id).appendTo(tbody) + row.append(''+info.product.name+'') + row.append(''+info.number+'') + row.append(''+Qrammer.currency(info.product.price * info.number)+'') + x_btn = $('').click(-> delete(window.active_list[product_id]) && Qrammer.build_product_list() ) + row.append($('').append(x_btn)) + $('#active-order-total').html(Qrammer.currency(total)) + table.show() + clear_active_list: -> + window.active_list = {} + $('#active-order-table').hide() + order_active_list: (post_uri)-> + h = {list_id: active_list_id} + for product_id, info of window.active_list + h['products['+product_id+']'] = info.number + $.post(post_uri, h, ((res) -> Qrammer.handle_response(res)), 'json') + handle_response: (res) -> + if(typeof(res) == 'string') + return unless res.length + if res[0] == '{' + res = JSON.parse(res) + else + eval(res) + return + alert(res['message']) if res['message'] && !res['ok'] + alert(res['message']) if res['message'] && res['ok'] + load_active_order_list: (supplier_id) -> + $.get('/suppliers/'+supplier_id+'/active_order_list.json', (res) -> + body = $('#active-orders-table tbody') + body.find('tr').remove() + foot = $('#active-orders-table tfoot') + if(!res.orders && !res.orders.length) + alert('No orders in list'); + return; + for order in res.orders + order_txts = [] + row = $('').appendTo(body) + process_btn = $('') + process_callback = ( (ord) -> + -> + my_btn = $(this) + $.post('/orders/'+ord.id+'/is_being_processed', {}, (res)-> my_btn.remove()) + )(order) + process_btn.click(process_callback) + + delivered_btn = $('') + delivered_callback = ( (ord, r) -> + -> + my_btn = $(this) + $.post('/orders/'+ord.id+'/is_delivered', {}, (res)-> r.slideUp('slow')) + )(order, row) + delivered_btn.click(delivered_callback) + for product in order.products + order_txts.push(product.name + ' (' + product['number'] + ')') + row.append($('').text(order_txts.join(', '))) + row.append($('').text(order.table_number)) + row.append($('').html(Qrammer.currency(order.total_amount))) + td_buttons = $('') + td_buttons.append(process_btn).append(' ') if order.state == 'placed' + td_buttons.append(delivered_btn) + row.append(td_buttons) + #foot.append(''+Qrammer.currency(res.total_amount)+''); + ) + load_active_lists: (supplier_id) -> + $.get('/suppliers/'+supplier_id+'/active_lists.json', (res) -> + body = $('#active-lists-table tbody') + body.find('tr').remove() + foot = $('#active-lists-table tfoot') + for list in res.lists + order_txts = [] + row = $('').appendTo(body) + close_btn = $('') + close_callback = ( (lst, r) -> + -> + my_btn = $(this) + $.post('/lists/'+lst._id+'/is_closed', {}, (res)-> r.slideUp('slow')) + )(list, row) + close_btn.click(close_callback) + + row.append($('').text(list._id)) + row.append($('').html(Qrammer.currency(list.total_amount))) + td_buttons = $('') + td_buttons.append(close_btn) + row.append(td_buttons) + #foot.append(''+Qrammer.currency(res.total_amount)+''); + ) + + build_product_list_as_modal: -> wrapper = $('') callback_wrapper = -> wrapper.modal('hide') @@ -50,4 +145,7 @@ root.Qrammer = .append($('Yes').click(callback_wrapper)) .appendTo(wrapper) wrapper.modal() - + +jQuery.ajaxSetup + 'beforeSend': (xhr) -> + xhr.setRequestHeader("Accept", "text/javascript") diff --git a/app/assets/stylesheets/structure.css.sass b/app/assets/stylesheets/structure.css.sass new file mode 100644 index 00000000..63b77bf9 --- /dev/null +++ b/app/assets/stylesheets/structure.css.sass @@ -0,0 +1,33 @@ +table + thead + th + &.currency + text-align: right + tbody + td + &.currency + text-align: right + &.numeric + text-align: right + &.actions + text-align: right + tfoot + td + &.currency + text-align: right +#active-list-table + tbody + tr + td + &:first-child + padding-left: 35px + background-position: 5px center + background-repeat: no-repeat + &.placed + td + &:first-child + background-image: image-url('icons/order-check.png') + &.delivered + td + &:first-child + background-image: image-url('icons/order-doublecheck.png') diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 258705b5..450d8692 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,10 +1,31 @@ class ApplicationController < ActionController::Base + protect_from_forgery private - def active_list - List.find(session[:list_id]) + def check_active_list_state + if session[:active_list_id] + unless active_list.active? + session[:active_list_id] = nil + redirect_to root_path, alert: t('messages.the_list_has_been_closed') + end + end + end + + def active_list + return nil unless session[:active_list_id] + @active_list ||= List.find(session[:active_list_id]) + end + + def js_alert(message) + {ok: false, message: message}.to_json + end + def js_notice(message) + {ok: true, message: message}.to_json + end + + helper_method :active_list end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 6860fdc3..5d734330 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -1,5 +1,6 @@ class DashboardController < ApplicationController + before_filter :check_active_list_state, except: :home def home end @@ -17,8 +18,8 @@ class DashboardController < ApplicationController @list = List.new(table: @table) #@list.add_user(current_user) @list.save - session[:list_id] = @list.id - redirect_to root_path + session[:active_list_id] = @list.id + redirect_to action: :show_products end end @@ -27,4 +28,28 @@ class DashboardController < ApplicationController end + + def order_active_list + respond_to do |format| + format.html do + redirect_to(root_path, alert: t('messages.cannot_order_without_list_id')) and return if params[:list_id].blank? + @list = List.find(params[:list_id]) + redirect_to(root_path, alert: t('messages.cannot_order_on_non_active_list')) and return unless @list.active? + @list.place_order params[:products] + redirect_to root_path, notice: t('messages.order_is_placed') + end + format.js do + render js: js_alert(t('messages.cannot_order_without_list_id')) and return if params[:list_id].blank? + @list = List.find(params[:list_id]) + render js: js_alert(t('messages.cannot_order_on_non_active_list')) and return unless @list.active? + @list.place_order params[:products] + render js: js_notice( t('messages.order_is_placed') ) + end + end + end + + def view_active_list + redirect_to(root_path, alert: t('messages.there_is_no_list_active')) and return unless session[:active_list_id].present? + + end end diff --git a/app/controllers/lists_controller.rb b/app/controllers/lists_controller.rb index b2a888f5..47570537 100644 --- a/app/controllers/lists_controller.rb +++ b/app/controllers/lists_controller.rb @@ -82,6 +82,40 @@ class ListsController < ApplicationController end end + def current + @list = List.find(params[:id]) + @list.orders.include_relations(product_orders: :product) + respond_to do |format| + format.json do + h = @list.as_json + h[:orders] = [] + list_total = 0.0 + for order in @list.orders + ho = {products: []} + order_total = 0.0 + for product_order in order.product_orders + order_total += (product_order.amount * product_order.product.price).round(2) + ho[:products] << {name: product_order.product.name, id: product_order.product_id, number: product_order.amount, price: product_order.product.price} + end + ho[:total_amount] = order_total.round(2) + ho[:state] = order.state + list_total += ho[:total_amount] + h[:orders] << ho + end + h[:total_amount] = list_total.round(2) + render json: h + end + + end + + end + + # POST /orders/1/is_delivered + def is_closed + @list = List.find(params[:id]) + @list.close! + render nothing: true + end private def set_relation_options diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb new file mode 100644 index 00000000..2d8e8e3c --- /dev/null +++ b/app/controllers/orders_controller.rb @@ -0,0 +1,104 @@ +class OrdersController < ApplicationController + before_filter :set_relation_options, only: [:new, :edit, :create, :update] + # GET /orders + # GET /orders.json + def index + @orders = Order.all + + respond_to do |format| + format.html # index.html.erb + format.json { render json: @orders } + end + end + + # GET /orders/1 + # GET /orders/1.json + def show + @order = Order.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.json { render json: @order } + end + end + + # GET /orders/new + # GET /orders/new.json + def new + @order = Order.new + + respond_to do |format| + format.html # new.html.erb + format.json { render json: @order } + end + end + + # GET /orders/1/edit + def edit + @order = Order.find(params[:id]) + end + + # POST /orders + # POST /orders.json + def create + @order = Order.new(params[:order]) + + respond_to do |format| + if @order.save + format.html { redirect_to @order, notice: t('action.create.successfull', model: Order.model_name.human) } + format.json { render json: @order, status: :created, location: @order } + else + format.html { render action: "new" } + format.json { render json: @order.errors, status: :unprocessable_entity } + end + end + end + + # PUT /orders/1 + # PUT /orders/1.json + def update + @order = Order.find(params[:id]) + + respond_to do |format| + if @order.update_attributes(params[:order]) + format.html { redirect_to @order, notice: t('action.update.successfull', model: Order.model_name.human) } + format.json { head :no_content } + else + format.html { render action: "edit" } + format.json { render json: @order.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /orders/1 + # DELETE /orders/1.json + def destroy + @order = Order.find(params[:id]) + @order.destroy + + respond_to do |format| + format.html { redirect_to orders_url, notice: t('action.destroy.successfull', model: Order.model_name.human) } + format.json { head :no_content } + end + end + + # POST /orders/1/is_being_processed + def is_being_processed + @order = Order.find(params[:id]) + @order.is_being_processed! + render nothing: true + end + + # POST /orders/1/is_delivered + def is_delivered + @order = Order.find(params[:id]) + @order.is_delivered! + render nothing: true + end + + private + + def set_relation_options + @lists = List.all + end +end diff --git a/app/controllers/suppliers_controller.rb b/app/controllers/suppliers_controller.rb index 1a4b1241..943ff279 100644 --- a/app/controllers/suppliers_controller.rb +++ b/app/controllers/suppliers_controller.rb @@ -98,6 +98,58 @@ class SuppliersController < ApplicationController end end end + + # GET /suppliers/1/active_order_list + # GET /suppliers/1/active_order_list.json + def active_order_list + @supplier = Supplier.find(params[:id]) + respond_to do |format| + format.html + format.json do + h = @supplier.as_json + h[:orders] = [] + list_total = 0.0 + for order in @supplier.active_orders + ho = {products: []} + order_total = 0.0 + for product_order in order.product_orders + order_total += (product_order.amount * product_order.product.price).round(2) + ho[:products] << {name: product_order.product.name, id: product_order.product_id, number: product_order.amount, price: product_order.product.price} + end + ho[:total_amount] = order_total.round(2) + ho[:state] = order.state + ho[:table_number] = order.table_number + ho[:id] = order.id + list_total += ho[:total_amount] + h[:orders] << ho + end + h[:total_amount] = list_total.round(2) + render json: h + end + end + end + + # GET /suppliers/1/active_lists + # GET /suppliers/1/active_lists.json + def active_lists + @supplier = Supplier.find(params[:id]) + respond_to do |format| + format.html + format.json do + h = @supplier.as_json + h[:lists] = [] + grand_total = 0.0 + for list in @supplier.active_lists + hl = list.as_json + hl[:total_amount] = list.orders.inject(0.0){|sum, o| sum + o.product_orders.inject(0.0){|s, po| s + (po.amount * po.product.price).round(2)}}.round(2) + grand_total += hl[:total_amount] + h[:lists] << hl + end + h[:total_amount] = grand_total.round(2) + render json: h + end + end + end private def set_relation_options diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 9a1aef14..17235e98 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -19,7 +19,7 @@ module ApplicationHelper end def list_open? - session[:list_id].present? + session[:active_list_id].present? end def no_content_given(model) diff --git a/app/models/list.rb b/app/models/list.rb index 183f1d8f..a0077d5d 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -1,15 +1,18 @@ class List include SimplyStored::Couch - property :state + property :state, default: 'active' # active, #closed + property :need_help, type: :boolean, default: false + property :needs_payment, type: :boolean, default: false property :closed_at, type: Time - has_many :orders + has_many :orders, dependent: :destroy belongs_to :table has_and_belongs_to_many :users, storing_keys: true validates :table_id, presence: true def close! + #TODO: close orders self.state = 'closed' self.closed_at = Time.now save @@ -18,4 +21,18 @@ class List def supplier table.supplier end + + def active? + state == 'active' + end + + def place_order(products) + return unless products.any? + @order = Order.create list: self, supplier: supplier + return unless @order.id + products.each do |product_id, number| + number = number.to_i + ProductOrder.create order: @order, product_id: product_id, amount: number if number > 0 + end + end end diff --git a/app/models/order.rb b/app/models/order.rb index dcf5576c..14899e4a 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,9 +1,45 @@ class Order include SimplyStored::Couch + property :state, default: 'placed' # placed, active, delivered, cancelled + belongs_to :list belongs_to :user + belongs_to :supplier - has_many :product_orders - has_many :products, through: :product_orders + has_many :product_orders, dependent: :destroy + #has_many :products, through: :product_orders + validates :supplier_id, presence: true + + view :active_for_supplier_view, type: :custom, map_function: %[function(doc){ + if(doc.ruby_class == 'Order' && (doc.state == 'placed' || doc.state == 'active')){ + emit(doc.supplier_id, 1); + } + }], reduce_function: '_sum' + + def self.active_for_supplier(supplier_id) + database.view(active_for_supplier_view(key: supplier_id, reduce: false, include_docs: true)) + end + def table_number + list.table.number + end + alias table_nr table_number + + + def placed? + state == 'placed' + end + def active? + state == 'active' + end + + def is_being_processed! + self.state = 'active' + save + end + + def is_delivered! + self.state = 'delivered' + save + end end diff --git a/app/models/product_order.rb b/app/models/product_order.rb index d0286dfc..76a1b54c 100644 --- a/app/models/product_order.rb +++ b/app/models/product_order.rb @@ -1,6 +1,9 @@ class ProductOrder include SimplyStored::Couch - + + property :amount, type: Fixnum + belongs_to :product belongs_to :order + end diff --git a/app/models/supplier.rb b/app/models/supplier.rb index d869d251..b2b7096f 100644 --- a/app/models/supplier.rb +++ b/app/models/supplier.rb @@ -2,9 +2,31 @@ class Supplier include SimplyStored::Couch property :name - has_many :lists - has_many :orders, through: :lists - has_many :products - has_many :product_categories - has_many :tables + #has_many :orders, through: :lists + has_many :products, dependent: :destroy + has_many :product_categories, dependent: :destroy + has_many :tables, dependent: :destroy + #has_many :lists, through: :tables + has_many :orders + + def active_orders + return @active_orders if @active_orders + @active_orders = Order.active_for_supplier(id) + @active_orders.include_relation(list: :table, product_orders: :order) + @active_orders + end + + def active_lists + return @active_lists if @active_lists + @tables ||= active_tables + @tables.include_relation(:lists) + @active_lists = @tables.map(&:lists).flatten.select(&:active?) + @active_lists.include_relations(:table, orders: {product_orders: :product}) + end + + + def active_tables + tables + end + end diff --git a/app/views/dashboard/home.html.slim b/app/views/dashboard/home.html.slim index 7ca57290..ae7f30df 100644 --- a/app/views/dashboard/home.html.slim +++ b/app/views/dashboard/home.html.slim @@ -1,14 +1,14 @@ .page-header= title 'Home' ul.nav.nav-tabs.nav-stacked - if list_open? - li.active= link_to '€ 23,45'.html_safe, '#' li= link_to 'Place order', '/show_products?supplier_id=' + active_list.supplier.id - li= link_to 'Active list', '#' + li= link_to 'Active list', view_active_list_path li= link_to 'Request bill', '#' li= link_to 'I have a question', '#' - else li= link_to 'Place order', '/select_qrcode' li= link_to 'Subscribe to list', '#' + li= link_to 'Check out menu', '#' ul.nav.nav-tabs.nav-stacked li= link_to 'View history', '#' diff --git a/app/views/dashboard/show_products.html.slim b/app/views/dashboard/show_products.html.slim index c99ac7dc..33eaa156 100644 --- a/app/views/dashboard/show_products.html.slim +++ b/app/views/dashboard/show_products.html.slim @@ -1,6 +1,24 @@ button onClick='Qrammer.build_product_list()' class='btn btn-inverse'Lijst table#products-table.table.table-striped.table-hover tbody +- content_for :sidebar do + table#active-order-table.table.hide + thead + tr + th Product + th # + th.currency Total + th + tbody + tfoot + tr + td colspan=2 + button class="btn btn-primary" onClick="Qrammer.order_active_list('/order_active_list')" Bestellen + |  + button class="btn btn btn-warning" onClick="Qrammer.clear_active_list()" Clear + td.currency + strong#active-order-total + td - content_for :footer do javascript: jQuery(function(){ @@ -8,12 +26,12 @@ table#products-table.table.table-striped.table-hover window.products = res body = $('#products-table tbody') for(var category in window.products){ - body.append('

'+category+'

'); + body.append('

'+category+'

'); var category_ref = window.products[category]; for(var iproduct = 0; iproduct < window.products[category].length; iproduct++){ var product_index = iproduct; row = $(''); - button = $(''); + button = $(''); var callback = (function(ref){ return function(){ Qrammer.add_product(ref[product_index]) } })(category_ref) diff --git a/app/views/dashboard/view_active_list.html.slim b/app/views/dashboard/view_active_list.html.slim new file mode 100644 index 00000000..064bb10b --- /dev/null +++ b/app/views/dashboard/view_active_list.html.slim @@ -0,0 +1,37 @@ +.page-header + h1 List overview +table#active-list-table.table + thead + tr + th Order + th.currency Price + tbody + tfoot +- content_for :footer do + javascript: + jQuery(function(){ + $.get('#{current_list_path(session[:active_list_id], format: :json).html_safe}', function(res){ + var body = $('#active-list-table tbody'); + var foot = $('#active-list-table tfoot'); + if(!res.orders && !res.orders.length){ + alert('No orders in list'); + return; + } + for(var iorder = 0; iorder < res.orders.length; iorder++){ + var order_txts = []; + var order = res.orders[iorder]; + var row = $('').appendTo(body); + row.addClass(order.state); + //if(order.state == 'placed') row.addClass('info'); + //if(order.state == 'delivered') row.addClass('success'); + if(order.state == 'cancelled') row.addClass('error'); + for(var iproduct = 0; iproduct < order.products.length; iproduct++){ + var product = order.products[iproduct]; + order_txts.push(product.name + ' (' + product['number'] + ')') + } + row.append($('').text(order_txts.join(', '))); + row.append($('').html(Qrammer.currency(res.orders[iorder].total_amount))) + } + foot.append(''+Qrammer.currency(res.total_amount)+''); + }) + }) diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim index 1f69807d..f96e61fb 100644 --- a/app/views/layouts/application.html.slim +++ b/app/views/layouts/application.html.slim @@ -16,6 +16,8 @@ html lang="en" link href="images/apple-touch-icon-72x72.png" rel="apple-touch-icon-precomposed" sizes="72x72" link href="images/apple-touch-icon.png" rel="apple-touch-icon-precomposed" link href="images/favicon.ico" rel="shortcut icon" + javascript: + var active_list_id = #{session[:active_list_id] ? "'#{session[:active_list_id]}'" : 'null'}; body .navbar.navbar-fixed-top @@ -56,6 +58,7 @@ html lang="en" li.nav-header Links li= link_to "Home", root_path li= link_to "Companytools", 'http://www.companytools.nl/' + = yield :sidebar footer p © Companytools 2012 diff --git a/app/views/orders/_form.html.slim b/app/views/orders/_form.html.slim new file mode 100644 index 00000000..30cacca6 --- /dev/null +++ b/app/views/orders/_form.html.slim @@ -0,0 +1,14 @@ += form_for @order, html: {class: 'form-horizontal' } do |f| + = render 'error_messages', target: @order + .control-group class=(@order.errors[:state].any? ? 'error' : nil) + = f.label :state, class: 'control-label' + .controls + = f.text_field :state, class: 'text_field' + .control-group class=(@order.errors[:supplier_id].any? ? 'error' : nil) + = f.label :supplier_id, Supplier.model_name.human, class: 'control-label' + .controls + = f.select :supplier_id, options_for_select(@suppliers.map{|a| [a.name, a.id]}), include_blank: nil + .form-actions + = f.submit nil, class: 'btn btn-primary' + ' + = link_to t("helpers.links.cancel"), orders_path, class: 'btn' diff --git a/app/views/orders/edit.html.slim b/app/views/orders/edit.html.slim new file mode 100644 index 00000000..b2fb432d --- /dev/null +++ b/app/views/orders/edit.html.slim @@ -0,0 +1,4 @@ +- model_class = Order +.page-header + = title :edit, model_class += render 'form' diff --git a/app/views/orders/index.html.slim b/app/views/orders/index.html.slim new file mode 100644 index 00000000..af117872 --- /dev/null +++ b/app/views/orders/index.html.slim @@ -0,0 +1,24 @@ +- model_class = Order +div.page-header= title :index, model_class +- if @orders.any? + table.table.table-striped + thead + tr + th= model_class.human_attribute_name(:state) + th= Supplier.model_name.human + th= model_class.human_attribute_name(:created_at) + th=t 'helpers.actions' + tbody + - @orders.each do |order| + tr + td= link_to order.state, order + td= link_to_if order.supplier.present?, order.supplier.try(:name), order.supplier + td=l order.created_at, format: :short + td + = link_to t('helpers.links.edit'), [:edit, order], class: 'btn btn-mini' + ' + = link_to t("helpers.links.destroy"), order, method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-mini btn-danger' +- else + = no_content_given model_class += link_to t("helpers.links.new"), new_order_path, class: 'btn btn-primary' + diff --git a/app/views/orders/new.html.slim b/app/views/orders/new.html.slim new file mode 100644 index 00000000..7963a2b0 --- /dev/null +++ b/app/views/orders/new.html.slim @@ -0,0 +1,4 @@ +- model_class = Order +.page-header + = title :new, model_class += render 'form' diff --git a/app/views/orders/show.html.slim b/app/views/orders/show.html.slim new file mode 100644 index 00000000..a268b3ad --- /dev/null +++ b/app/views/orders/show.html.slim @@ -0,0 +1,16 @@ +- model_class = Order +.page-header= title :show, @order + +dl.dl-horizontal.show-list + dt= model_class.human_attribute_name(:state) + dd= @order.state + - if @order.supplier.present? + dt= Supplier.model_name.human + dd= link_to @order.supplier.name, @order.supplier + +.form-actions + = link_to t("helpers.links.back"), orders_path, class: 'btn' + ' + = link_to t('helpers.links.edit'), [:edit, @order], class: 'btn' + ' + = link_to t("helpers.links.destroy"), @order, method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-danger' diff --git a/app/views/suppliers/active_lists.html.slim b/app/views/suppliers/active_lists.html.slim new file mode 100644 index 00000000..d3b6b082 --- /dev/null +++ b/app/views/suppliers/active_lists.html.slim @@ -0,0 +1,15 @@ +.page-header= title 'Active lists' +table#active-lists-table.table + thead + tr + th.number Table number + th.currency Price + th.actions + tbody +- content_for :footer do + javascript: + jQuery(function(){ + Qrammer.load_active_lists('#{@supplier.id}') + setInterval( "Qrammer.load_active_lists('#{@supplier.id}')", 7500); + }); + diff --git a/app/views/suppliers/active_order_list.html.slim b/app/views/suppliers/active_order_list.html.slim new file mode 100644 index 00000000..e9e37c6c --- /dev/null +++ b/app/views/suppliers/active_order_list.html.slim @@ -0,0 +1,16 @@ +.page-header= title 'Active orders' +table#active-orders-table.table + thead + tr + th Order + th.number Table number + th.currency Price + th.actions + tbody +- content_for :footer do + javascript: + jQuery(function(){ + Qrammer.load_active_order_list('#{@supplier.id}') + setInterval( "Qrammer.load_active_order_list('#{@supplier.id}')", 7500); + }); + diff --git a/app/views/users/_form.html.slim b/app/views/users/_form.html.slim index 2aa2049c..f1a17de6 100644 --- a/app/views/users/_form.html.slim +++ b/app/views/users/_form.html.slim @@ -1,41 +1,42 @@ = form_for @user, html: {class: 'form-horizontal' } do |f| - .control-group + = render 'error_messages', target: @user + .control-group class=(@user.errors[:email].any? ? 'error' : nil) = f.label :email, class: 'control-label' .controls = f.text_field :email, class: 'text_field' - .control-group + .control-group class=(@user.errors[:encrypted_password].any? ? 'error' : nil) = f.label :encrypted_password, class: 'control-label' .controls = f.text_field :encrypted_password, class: 'text_field' - .control-group + .control-group class=(@user.errors[:remember_token].any? ? 'error' : nil) = f.label :remember_token, class: 'control-label' .controls = f.text_field :remember_token, class: 'text_field' - .control-group + .control-group class=(@user.errors[:remember_created_at].any? ? 'error' : nil) = f.label :remember_created_at, class: 'control-label' .controls = f.text_field :remember_created_at, class: 'text_field' - .control-group + .control-group class=(@user.errors[:reset_password_token].any? ? 'error' : nil) = f.label :reset_password_token, class: 'control-label' .controls = f.text_field :reset_password_token, class: 'text_field' - .control-group + .control-group class=(@user.errors[:sign_in_count].any? ? 'error' : nil) = f.label :sign_in_count, class: 'control-label' .controls = f.text_field :sign_in_count, class: 'text_field' - .control-group + .control-group class=(@user.errors[:current_sign_in_at].any? ? 'error' : nil) = f.label :current_sign_in_at, class: 'control-label' .controls = f.text_field :current_sign_in_at, class: 'text_field' - .control-group + .control-group class=(@user.errors[:last_sign_in_at].any? ? 'error' : nil) = f.label :last_sign_in_at, class: 'control-label' .controls = f.text_field :last_sign_in_at, class: 'text_field' - .control-group + .control-group class=(@user.errors[:current_sign_in_ip].any? ? 'error' : nil) = f.label :current_sign_in_ip, class: 'control-label' .controls = f.text_field :current_sign_in_ip, class: 'text_field' - .control-group + .control-group class=(@user.errors[:last_sign_in_ip].any? ? 'error' : nil) = f.label :last_sign_in_ip, class: 'control-label' .controls = f.text_field :last_sign_in_ip, class: 'text_field' diff --git a/app/views/users/index.html.slim b/app/views/users/index.html.slim index c0e37557..669c9c8f 100644 --- a/app/views/users/index.html.slim +++ b/app/views/users/index.html.slim @@ -1,38 +1,22 @@ - model_class = User -div class="page-header"= title :index, model_class -table class="table table-striped" - thead - tr - th= model_class.human_attribute_name(:email) - th= model_class.human_attribute_name(:encrypted_password) - th= model_class.human_attribute_name(:remember_token) - th= model_class.human_attribute_name(:remember_created_at) - th= model_class.human_attribute_name(:reset_password_token) - th= model_class.human_attribute_name(:sign_in_count) - th= model_class.human_attribute_name(:current_sign_in_at) - th= model_class.human_attribute_name(:last_sign_in_at) - th= model_class.human_attribute_name(:current_sign_in_ip) - th= model_class.human_attribute_name(:last_sign_in_ip) - th= model_class.human_attribute_name(:created_at) - th=t 'helpers.actions' - tbody - - @users.each do |user| +div.page-header= title :index, model_class +- if @users.any? + table.table.table-striped + thead tr - td= link_to user.email, user - td= user.encrypted_password - td= user.remember_token - td= user.remember_created_at - td= user.reset_password_token - td= user.sign_in_count - td= user.current_sign_in_at - td= user.last_sign_in_at - td= user.current_sign_in_ip - td= user.last_sign_in_ip - td=l user.created_at, format: :short - td - = link_to t('helpers.links.edit'), [:edit, user], class: 'btn btn-mini' - ' - = link_to t("helpers.links.destroy"), user, method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-mini btn-danger' - + th= model_class.human_attribute_name(:email) + th= model_class.human_attribute_name(:created_at) + th=t 'helpers.actions' + tbody + - @users.each do |user| + tr + td= link_to user.email, user + td=l user.created_at, format: :short + td + = link_to t('helpers.links.edit'), [:edit, user], class: 'btn btn-mini' + ' + = link_to t("helpers.links.destroy"), user, method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-mini btn-danger' +- else + = no_content_given model_class = link_to t("helpers.links.new"), new_user_path, class: 'btn btn-primary' diff --git a/app/views/users/show.html.slim b/app/views/users/show.html.slim index c81d71eb..4efb1d07 100644 --- a/app/views/users/show.html.slim +++ b/app/views/users/show.html.slim @@ -1,27 +1,26 @@ - model_class = User -.page-header - = title :show, @user +.page-header= title :show, @user dl.dl-horizontal.show-list - dt= model_class.human_attribute_name(:email) + ':' + dt= model_class.human_attribute_name(:email) dd= @user.email - dt= model_class.human_attribute_name(:encrypted_password) + ':' + dt= model_class.human_attribute_name(:encrypted_password) dd= @user.encrypted_password - dt= model_class.human_attribute_name(:remember_token) + ':' + dt= model_class.human_attribute_name(:remember_token) dd= @user.remember_token - dt= model_class.human_attribute_name(:remember_created_at) + ':' + dt= model_class.human_attribute_name(:remember_created_at) dd= @user.remember_created_at - dt= model_class.human_attribute_name(:reset_password_token) + ':' + dt= model_class.human_attribute_name(:reset_password_token) dd= @user.reset_password_token - dt= model_class.human_attribute_name(:sign_in_count) + ':' + dt= model_class.human_attribute_name(:sign_in_count) dd= @user.sign_in_count - dt= model_class.human_attribute_name(:current_sign_in_at) + ':' + dt= model_class.human_attribute_name(:current_sign_in_at) dd= @user.current_sign_in_at - dt= model_class.human_attribute_name(:last_sign_in_at) + ':' + dt= model_class.human_attribute_name(:last_sign_in_at) dd= @user.last_sign_in_at - dt= model_class.human_attribute_name(:current_sign_in_ip) + ':' + dt= model_class.human_attribute_name(:current_sign_in_ip) dd= @user.current_sign_in_ip - dt= model_class.human_attribute_name(:last_sign_in_ip) + ':' + dt= model_class.human_attribute_name(:last_sign_in_ip) dd= @user.last_sign_in_ip .form-actions diff --git a/config/locales/en.yml b/config/locales/en.yml index 4db28813..81b22893 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,6 +1,5 @@ # Sample localization file for English. Add more files in this directory for other locales. # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. - en: hello: "Hello world" helpers: @@ -9,6 +8,11 @@ en: forms: errors: title: There are problems found during saving (%{count}) + messages: + cannot_order_without_list_id: You cannot place an order without specifying a list + cannot_order_on_non_active_list: You cannot place an order on a closed list + order_is_placed: Your order has been received in good order + the_list_has_been_closed: The list has been closed action: index: label: Listing %{models} diff --git a/config/routes.rb b/config/routes.rb index 37f14237..ed62b2f1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,16 +5,30 @@ Qrammer::Application.routes.draw do get :qrcode end end + resources :orders do + member do + post :is_being_processed + post :is_delivered + end + end resources :suppliers do member do get :product_list + get :active_order_list + get :active_lists + end + end + resources :lists do + member do + get :current + post :is_closed end end - resources :lists resources :products resources :product_categories match "/:action", controller: 'dashboard' + match '/view_active_list' => 'dashboard#view_active_list', as: :view_active_list # The priority is based upon order of creation: # first created -> highest priority. diff --git a/stories b/stories index f334df26..b2e16f50 100644 --- a/stories +++ b/stories @@ -12,6 +12,7 @@ Person actions: When no list is open: - Open list - Subscribe to existing list + - Request menu General actions - View history @@ -21,3 +22,17 @@ Person actions: Alleen restaurant kan rekening afsluiten, als dit nog niet is gebeurd voor een tafel kan een nieuwe persoon geen lijst openen. Alert melding bij restaurant als iemand dit probeert Eén lijst tegelijk actief? (wel handig en duidelijk!!!) + + +Sales arguments: +- Safer because of personalized ordering, less incentive to leave without payment +- No installation required, just internet +- Plaats een overzicht op meerdere plaatsen voor een optimaal service level + +Actielijst: +- Real life test @ flex@diem +- Hoe omgaan met delivered -> on the way +- processen noteren en observeren (reverse) in cafe +- Bewoordingen critisch en klantgericht doornemen +- Plaats omgevingen in ihpone / ipad omgeving (gerelateerd) +- Barman en vaste tafels