diff --git a/app/assets/images/icons/orders-queue.png b/app/assets/images/icons/orders-queue.png new file mode 100644 index 00000000..654e181d Binary files /dev/null and b/app/assets/images/icons/orders-queue.png differ diff --git a/app/assets/images/icons/orders-queue.svg b/app/assets/images/icons/orders-queue.svg new file mode 100644 index 00000000..7a417802 --- /dev/null +++ b/app/assets/images/icons/orders-queue.svg @@ -0,0 +1,128 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/javascripts/user/quser.js.coffee b/app/assets/javascripts/user/quser.js.coffee index 93345241..7ebe3a47 100644 --- a/app/assets/javascripts/user/quser.js.coffee +++ b/app/assets/javascripts/user/quser.js.coffee @@ -44,6 +44,10 @@ class Quser else if(e.event == 'new_order') $('#active-list-table tbody').append @mustache('#active-list-order-template', new Order(e.data.order)) $('.list-total-amount').html(currency(e.data.total_amount)) + else if(e.event == 'orders_in_process_count') + $('.supplier-orders-in-process-count').text(e.data.count || 0) + else if(e.event == 'orders_placed_count') + $('.supplier-orders-placed-count').text(e.data.count || 0) console.log(e) false ensure_json: (res)-> @@ -97,6 +101,9 @@ class Quser $('.table-number').text(response.table_number) if response.table_number $('.supplier-name').text(response.supplier_name) if response.supplier_name + $('.supplier-orders-placed-count').text(response.supplier_orders_placed_count || 0) + $('.supplier-orders-in-process-count').text(response.supplier_orders_in_process_count || 0) + if response.not_present || response.list_active == false then $('.home-link').removeClass('active') else $('.home-link').addClass('active') diff --git a/app/assets/stylesheets/user/header.css.sass b/app/assets/stylesheets/user/header.css.sass new file mode 100644 index 00000000..193515a2 --- /dev/null +++ b/app/assets/stylesheets/user/header.css.sass @@ -0,0 +1,20 @@ +.supplier-info-row + clear: right +.supplier-orders-in-process-count + background-image: image-url('icons/order-check.png') + padding-left: 20px + padding-right: 6px +.supplier-orders-delivered-count + background-image: image-url('icons/order-doublecheck.png') + padding-left: 28px +.supplier-orders-placed-count + background-image: image-url('icons/orders-queue.png') + padding-left: 22px + padding-right: 6px + //padding-top: 4px + //padding-top: 4px +.top-button-bar + .counter + display: inline + background-repeat: no-repeat + background-position: left center diff --git a/app/assets/stylesheets/user/qr_list.css.sass b/app/assets/stylesheets/user/qr_list.css.sass index a24e5907..32a34089 100644 --- a/app/assets/stylesheets/user/qr_list.css.sass +++ b/app/assets/stylesheets/user/qr_list.css.sass @@ -4,3 +4,6 @@ li list-style: none margin-bottom: 8px + .qr-image + background-color: white + display: block diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 9651ec6a..86b3731f 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -23,8 +23,18 @@ class DashboardController < ApplicationController size = RQRCode.minimum_qr_size_from_string(code) respond_to do |format| format.html - format.svg { render :qrcode => code, :level => :l, :unit => 10, table_number: @table.number, qcontainer: true } - format.png { render qrcode: code, level: :l, table_number: @table.number, qcontainer: true } + format.svg { render qrcode: code, level: :l, unit: 10, table_number: @table.number, qcontainer: true } + format.png do + #render qrcode: code, level: :l, table_number: @table.number, qcontainer: true + size = RQRCode.minimum_qr_size_from_string(code) + level = :l + qrcode = RQRCode::QRCode.new(code, size: size, level: level) + svg = RQRCode::Renderers::SVG::render(qrcode) + svg_file = Tempfile.new(['table_qr', '.svg']){|f| f.puts svg} + png_target = svg_file.path.sub /svg$/, 'png' + + render nothing: true + end end end diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 8c1f15f7..ecf99f59 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -184,7 +184,7 @@ class UserController < ApplicationController end format.json do render json: js_alert(t('messages.the_list_has_been_closed')) and return unless list.present? - render json: list.with_orders_and_join_requests_as_json.merge(supplier_name: list.supplier.name) + render json: list.with_orders_and_join_requests_and_supplier_info_as_json end end end diff --git a/app/models/list.rb b/app/models/list.rb index a69b0616..c49ce6ba 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -270,7 +270,7 @@ class List return false unless user order = Order.create list: self, supplier: supplier, user: user, section_id: section_id return unless order.id - orders_in_process_count = supplier.increment_orders_in_process_count! + orders_placed_count = supplier.increment_orders_placed_count! loaded_products = self.class.database.load_document products.keys products.each do |product_id, quantity| quantity = quantity.to_i @@ -281,11 +281,11 @@ class List save for user_id in user_ids broadcast_user user_id, 'new_order', order: order.with_products_as_json, total_amount: price - broadcast_user user_id, 'orders_in_process_count', count: orders_in_process_count + broadcast_user user_id, 'orders_placed_count', count: orders_placed_count end broadcast_supplier supplier.id, 'list_update', active_model_serializer.new(self).as_json broadcast_supplier supplier.id, 'new_order', OrderSerializer.new(order) - broadcast_supplier supplier.id, 'orders_in_process_count', count: orders_in_process_count + broadcast_supplier supplier.id, 'orders_placed_count', count: orders_placed_count order end @@ -323,6 +323,14 @@ class List @with_orders_and_join_requests_as_json = with_orders_as_json.merge(join_requests_as_json) end + def with_orders_and_join_requests_and_supplier_info_as_json + with_orders_and_join_requests_as_json.merge( + supplier_name: supplier.name, + supplier_orders_in_process_count: supplier.orders_in_process_count, + supplier_orders_placed_count: supplier.orders_placed_count + ) + end + def has_active_orders? Order.count_active_for_supplier_and_list(supplier_id, id) > 0 end diff --git a/app/models/order.rb b/app/models/order.rb index 92f23242..e1219cb3 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -78,29 +78,29 @@ class Order def is_being_processed! self.state = 'active' if save - orders_in_process_count = supplier.decrement_orders_in_process_count! - orders_delivered_count = supplier.increment_orders_delivered_count! + orders_in_process_count = supplier.increment_orders_in_process_count! + orders_placed_count = supplier.decrement_orders_placed_count! for user_id in list.user_ids broadcast_user user_id, 'order_being_processed', id: id, list_id: list_id broadcast_user user_id, 'orders_in_process_count', count: orders_in_process_count - broadcast_user user_id, 'orders_delivered_count', count: orders_delivered_count + broadcast_user user_id, 'orders_placed_count', count: orders_placed_count end broadcast_supplier supplier_id, 'order_being_processed', id: id, list_id: list_id broadcast_supplier supplier_id, 'orders_in_process_count', count: orders_in_process_count - broadcast_supplier supplier_id, 'orders_delivered_count', count: orders_delivered_count + broadcast_supplier supplier_id, 'orders_placed_count', count: orders_placed_count end end def is_delivered! self.state = 'delivered' if save - orders_delivered_count = supplier.decrement_orders_delivered_count! + orders_in_process_count = supplier.decrement_orders_in_process_count! for user_id in list.user_ids broadcast_user user_id, 'order_being_delivered', id: id, list_id: list_id - broadcast_user user_id, 'orders_delivered_count', count: orders_delivered_count + broadcast_user user_id, 'orders_in_process_count', count: orders_in_process_count end broadcast_supplier supplier_id, 'order_being_delivered', id: id, list_id: list_id - broadcast_supplier supplier_id, 'orders_delivered_count', count: orders_delivered_count + broadcast_supplier supplier_id, 'orders_in_process_count', count: orders_in_process_count end end diff --git a/app/models/supplier.rb b/app/models/supplier.rb index b8143382..60cc3bf0 100644 --- a/app/models/supplier.rb +++ b/app/models/supplier.rb @@ -116,6 +116,9 @@ class Supplier end def self.reset_counters! + + Qwaiter::Couchbase.design_doc('supplier').counters(reduce: false).each{|counter| Qwaiter::Counter.set counter.key, 0} + spec = Order.by_supplier_id_and_state(reduce: true, group_level: 2) reset_order_counters_with_spec spec end @@ -137,8 +140,8 @@ class Supplier Array.wrap(results['rows']).each do |result| supplier_id, state = result['key'] case state - when 'placed' then Qwaiter::Counter.set "supplier:#{supplier_id}:orders_in_process", result['value'] - when 'active' then Qwaiter::Counter.set "supplier:#{supplier_id}:orders_delivered", result['value'] + when 'placed' then Qwaiter::Counter.set "supplier_counter:#{supplier_id}:orders_placed", result['value'] + when 'active' then Qwaiter::Counter.set "supplier_counter:#{supplier_id}:orders_in_process", result['value'] end end end @@ -168,31 +171,31 @@ class Supplier end def increment_orders_in_process_count! - Qwaiter::Counter.incr "supplier:#{id}:orders_in_process" + Qwaiter::Counter.incr "supplier_counter:#{id}:orders_in_process" end - def increment_orders_delivered_count! - Qwaiter::Counter.incr "supplier:#{id}:orders_delivered" + def increment_orders_placed_count! + Qwaiter::Counter.incr "supplier_counter:#{id}:orders_placed" end def decrement_orders_in_process_count! - Qwaiter::Counter.decr "supplier:#{id}:orders_in_process" + Qwaiter::Counter.decr "supplier_counter:#{id}:orders_in_process" end - def decrement_orders_delivered_count! - Qwaiter::Counter.decr "supplier:#{id}:orders_delivered" + def decrement_orders_placed_count! + Qwaiter::Counter.decr "supplier_counter:#{id}:orders_placed" end def orders_in_process_count - Qwaiter::Counter.get "supplier:#{id}:orders_in_process" + Qwaiter::Counter.get "supplier_counter:#{id}:orders_in_process" end - def orders_delivered_count - Qwaiter::Counter.get "supplier:#{id}:orders_delivered" + def orders_placed_count + Qwaiter::Counter.get "supplier_counter:#{id}:orders_placed" end def active_order_count - orders_in_process_count + orders_delivered_count + orders_in_process_count + orders_placed_count end private diff --git a/app/views/dashboard/select_qrcode.html.slim b/app/views/dashboard/select_qrcode.html.slim index 1f427d2a..de9a603d 100644 --- a/app/views/dashboard/select_qrcode.html.slim +++ b/app/views/dashboard/select_qrcode.html.slim @@ -1,4 +1,4 @@ .page-header= title 'Select Qr code' ul#qr-list - for table in @tables - li= link_to_function image_tag(url_for(table_qr_image_path(table_id: table.id, format: :png))), %|Quser.actions_for_table({table_id: '#{table.id}'})| + li= link_to_function image_tag(url_for(table_qr_image_path(table_id: table.id, format: :svg)), class: 'qr-image'), %|Quser.actions_for_table({table_id: '#{table.id}'})| diff --git a/app/views/layouts/tablet.html.slim b/app/views/layouts/tablet.html.slim index 0c2a4147..b8dd78d9 100644 --- a/app/views/layouts/tablet.html.slim +++ b/app/views/layouts/tablet.html.slim @@ -28,7 +28,7 @@ html lang="en" ul.nav.pull-right li.dropdown a.dropdown-toggle href="#" data-toggle="dropdown" - = current_supplier.email + = current_supplier.name.presence || current_supplier.email b.caret ul.dropdown-menu - if current_supplier.open? diff --git a/app/views/user/active_list.html.slim b/app/views/user/active_list.html.slim index b7fcefd9..a47d80e8 100644 --- a/app/views/user/active_list.html.slim +++ b/app/views/user/active_list.html.slim @@ -1,7 +1,11 @@ = top_bar title: 'active_list.title' do .pull-right - .table-number - .supplier-name + .supplier-info-row + .table-number + .supplier-name + .supplier-info-row + .counter.supplier-orders-placed-count + .counter.supplier-orders-in-process-count .action-buttons = link_to content_tag(:span, t('helpers.links.place_order')), user_list_products_path, class: ['user-top-button'], id: 'place-order-on-list' span#list-needs-payment-button.user-top-button diff --git a/app/views/user/list_products.html.slim b/app/views/user/list_products.html.slim index fefadd68..30d8627f 100644 --- a/app/views/user/list_products.html.slim +++ b/app/views/user/list_products.html.slim @@ -1,7 +1,11 @@ = top_bar title: 'show_products.title' do .pull-right - .table-number - .supplier-name + .supplier-info-row + .table-number + .supplier-name + .supplier-info-row + .counter.supplier-orders-placed-count + .counter.supplier-orders-in-process-count .action-buttons = link_to user_active_list_path, class: ['user-top-button'], id: 'show-active-list' do span= t('helpers.links.show_active_list', list: List.model_name.human) diff --git a/app/views/user/list_products_for_table.html.slim b/app/views/user/list_products_for_table.html.slim index fcbbb2f1..270bba0d 100644 --- a/app/views/user/list_products_for_table.html.slim +++ b/app/views/user/list_products_for_table.html.slim @@ -1,7 +1,11 @@ = top_bar title: 'show_products.title' do .pull-right - .table-number - .supplier-name + .supplier-info-row + .table-number + .supplier-name + .supplier-info-row + .counter.supplier-orders-placed-count + .counter.supplier-orders-in-process-count .well table#products-table.table.table-hover tbody diff --git a/config/couchbase/design_docs/supplier.json b/config/couchbase/design_docs/supplier.json new file mode 100644 index 00000000..54e9f689 --- /dev/null +++ b/config/couchbase/design_docs/supplier.json @@ -0,0 +1,10 @@ +{ + "_id": "_design/supplier", + "language": "javascript", + "views": { + "counters": { + "map": "function(doc, meta){if(meta.id.match(/^supplier_counter/)) emit(meta.id, doc)}", + "reduce": "_sum" + } + } +} diff --git a/lib/qwaiter.rb b/lib/qwaiter.rb index e9602876..2baa638e 100644 --- a/lib/qwaiter.rb +++ b/lib/qwaiter.rb @@ -6,6 +6,7 @@ module Qwaiter autoload :Serializer autoload :Counter autoload :Broadcaster + autoload :Couchbase def self.broadcast_user(uid, event, data) message = {channel: "/user/#{uid}", data: {event: event, data: data}} diff --git a/lib/qwaiter/couchbase.rb b/lib/qwaiter/couchbase.rb new file mode 100644 index 00000000..1969d4e6 --- /dev/null +++ b/lib/qwaiter/couchbase.rb @@ -0,0 +1,17 @@ +module Qwaiter + module Couchbase + def self.connection + $cb + end + + def self.load_design_docs! + Dir.glob(Rails.root.join('config/couchbase/design_docs', "*.json")).each do |design_doc| + connection.save_design_doc File.open(design_doc) + end + end + + def self.design_doc(name) + connection.design_docs[name] + end + end +end diff --git a/lib/qwaiter/counter.rb b/lib/qwaiter/counter.rb index 894d9631..ba01f7a4 100644 --- a/lib/qwaiter/counter.rb +++ b/lib/qwaiter/counter.rb @@ -8,15 +8,16 @@ module Qwaiter end def self.get(key) - connection.get(key).to_i + connection.get(key, quiet: true).to_i end - def self.incr(*args) - connection.incr(*args) + def self.incr(key, options = {}) + options[:initial] ||= 0 + connection.incr(key, options) end - def self.decr(*args) - connection.decr(*args) + def self.decr(key, options = {}) + connection.decr(key, options) end end end diff --git a/lib/rqrcode-rails3.rb b/lib/rqrcode-rails3.rb index 0140e8ff..8add8517 100644 --- a/lib/rqrcode-rails3.rb +++ b/lib/rqrcode-rails3.rb @@ -16,7 +16,7 @@ module RQRCode qrcode = RQRCode::QRCode.new(string, :size => size, :level => level) svg = RQRCode::Renderers::SVG::render(qrcode, options) - + data = \ if format == :png image = MiniMagick::Image.read(svg) { |i| i.format "svg" } diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb index a8f0c9b6..b989e44c 100644 --- a/spec/models/list_spec.rb +++ b/spec/models/list_spec.rb @@ -138,11 +138,11 @@ describe List do expect{ list.place_order(user, product.id => 3) - }.to broadcast_to_user(user.id).message('orders_in_process_count').with(count: 2) + }.to broadcast_to_user(user.id).message('orders_placed_count').with(count: 2) expect{ list.place_order(user, product.id => 5) - }.to broadcast_to_supplier(supplier.id).message('orders_in_process_count').with(count: 3) + }.to broadcast_to_supplier(supplier.id).message('orders_placed_count').with(count: 3) end end diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb index aae251ab..dfa7d627 100644 --- a/spec/models/order_spec.rb +++ b/spec/models/order_spec.rb @@ -47,24 +47,24 @@ describe Order do describe 'counters' do before do # hack some initial values - Qwaiter::Counter.set "supplier:#{supplier.id}:orders_in_process", 7 - Qwaiter::Counter.set "supplier:#{supplier.id}:orders_delivered", 9 + Qwaiter::Counter.set "supplier_counter:#{supplier.id}:orders_placed", 11 + Qwaiter::Counter.set "supplier_counter:#{supplier.id}:orders_in_process", 7 end - it 'reduces the orders_in_process count and communicates it to user' do - expect{ order.is_being_processed! }.to broadcast_to_user(user.id).message( 'orders_in_process_count' ).with(count: 6) + it 'reduces the orders_placed count and communicates it to user' do + expect{ order.is_being_processed! }.to broadcast_to_user(user.id).message( 'orders_placed_count' ).with(count: 10) end - it 'increases the orders_delivered count and communicates it to user' do - expect{ order.is_being_processed! }.to broadcast_to_user(user.id).message( 'orders_delivered_count' ).with(count: 10) + it 'increases the orders_in_process count and communicates it to user' do + expect{ order.is_being_processed! }.to broadcast_to_user(user.id).message( 'orders_in_process_count' ).with(count: 8) end - it 'reduces the orders_in_process count and communicates it to supplier' do - expect{ order.is_being_processed! }.to broadcast_to_supplier(supplier.id).message( 'orders_in_process_count' ).with(count: 6) + it 'reduces the orders_placed count and communicates it to supplier' do + expect{ order.is_being_processed! }.to broadcast_to_supplier(supplier.id).message( 'orders_placed_count' ).with(count: 10) end it 'increases the orders_in_process count and communicates it to supplier' do - expect{ order.is_being_processed! }.to broadcast_to_supplier(supplier.id).message( 'orders_delivered_count' ).with(count: 10) + expect{ order.is_being_processed! }.to broadcast_to_supplier(supplier.id).message( 'orders_in_process_count' ).with(count: 8) end end @@ -82,16 +82,16 @@ describe Order do describe 'counters' do before do # hack some initial values - Qwaiter::Counter.set "supplier:#{supplier.id}:orders_in_process", 7 - Qwaiter::Counter.set "supplier:#{supplier.id}:orders_delivered", 9 + Qwaiter::Counter.set "supplier_counter:#{supplier.id}:orders_delivered", 11 + Qwaiter::Counter.set "supplier_counter:#{supplier.id}:orders_in_process", 7 end - it 'decreases the orders_delivered count and communicates it to user' do - expect{ order.is_delivered! }.to broadcast_to_user(user.id).message( 'orders_delivered_count' ).with(count: 8) + it 'decreases the orders_in_process count and communicates it to user' do + expect{ order.is_delivered! }.to broadcast_to_user(user.id).message( 'orders_in_process_count' ).with(count: 6) end it 'decreases the orders_in_process count and communicates it to supplier' do - expect{ order.is_delivered! }.to broadcast_to_supplier(supplier.id).message( 'orders_delivered_count' ).with(count: 8) + expect{ order.is_delivered! }.to broadcast_to_supplier(supplier.id).message( 'orders_in_process_count' ).with(count: 6) end end end diff --git a/spec/models/supplier_spec.rb b/spec/models/supplier_spec.rb index 3fa95242..6f366a55 100644 --- a/spec/models/supplier_spec.rb +++ b/spec/models/supplier_spec.rb @@ -11,9 +11,19 @@ describe Supplier do create_list :order, 7, :active, supplier: supplier1 create_list :order, 3, :placed, supplier: supplier2 Supplier.reset_counters! - supplier1.orders_in_process_count.should == 2 - supplier1.orders_delivered_count.should == 7 - supplier2.orders_in_process_count.should == 3 + supplier1.orders_placed_count.should == 2 + supplier1.orders_in_process_count.should == 7 + supplier2.orders_placed_count.should == 3 + end + + it 'cleans counter values if orders are no longer available' do + # this spec should run on the couchbase database + Qwaiter::Counter.connection = $cb + supplier = create :supplier + Qwaiter::Counter.set "supplier_counter:#{supplier.id}:orders_placed", 9 + supplier.orders_placed_count.should == 9 + Supplier.reset_counters! + supplier.orders_placed_count.should == 0 end end @@ -23,8 +33,8 @@ describe Supplier do create_list :order, 5, :placed, supplier: supplier create_list :order, 9, :active, supplier: supplier supplier.reset_counters! - supplier.orders_in_process_count.should == 5 - supplier.orders_delivered_count.should == 9 + supplier.orders_placed_count.should == 5 + supplier.orders_in_process_count.should == 9 end end @@ -83,10 +93,10 @@ describe Supplier do end - describe '#decrement_orders_delivered_count!' do - it 'decreases orders_delivered' do - Qwaiter::Counter.set "supplier:#{supplier.id}:orders_delivered", 9 - supplier.decrement_orders_delivered_count!.should == 8 + describe '#decrement_orders_placed_count!' do + it 'decreases orders_placed' do + Qwaiter::Counter.set "supplier_counter:#{supplier.id}:orders_placed", 9 + supplier.decrement_orders_placed_count!.should == 8 end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 892741a3..0df81fbb 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -46,6 +46,12 @@ end # NOT THREADSAFE!!!!!! but good enough for testing since the real couchbase flush is slowwwwww.... Qwaiter::Counter.connection = InMemoryQCounter.new +class Couchbase::View + alias :old_initialize :initialize + def initialize(bucket, endpoint, params = {}) + old_initialize(bucket, endpoint, params.merge(stale: false)) + end +end RSpec.configure do |config| # == Mock Framework @@ -100,6 +106,9 @@ RSpec.configure do |config| # examples within a transaction, remove the following line or assign false # instead of true. #config.use_transactional_fixtures = true + config.before :suite do + Qwaiter::Couchbase.load_design_docs! + end config.before :each do CouchPotato.couchrest_database.recreate! diff --git a/spec/support/in_memory_q_counter.rb b/spec/support/in_memory_q_counter.rb index 7ff5f560..e68bcec4 100644 --- a/spec/support/in_memory_q_counter.rb +++ b/spec/support/in_memory_q_counter.rb @@ -5,7 +5,7 @@ class InMemoryQCounter STORE = {} - def get(key) + def get(key, options = {}) STORE[key] end