diff --git a/app/assets/javascripts/supplier/app/controllers/application_controller.js.coffee b/app/assets/javascripts/supplier/app/controllers/application_controller.js.coffee index 8204dd7a..086112a4 100644 --- a/app/assets/javascripts/supplier/app/controllers/application_controller.js.coffee +++ b/app/assets/javascripts/supplier/app/controllers/application_controller.js.coffee @@ -15,6 +15,7 @@ App.ApplicationController = Ember.Controller.extend #@set 'supplier', null #@store.find('supplier', 'current').then success, error # @set 'supplier', @store.find('supplier', supplier_id) + current_employee: (-> @get('employee') ).property('employee') actions: signOut: -> window.location = Routes.destroy_employee_session_path() diff --git a/app/assets/javascripts/supplier/app/controllers/index_controller.js.coffee b/app/assets/javascripts/supplier/app/controllers/index_controller.js.coffee index f0f9d02d..46c72260 100644 --- a/app/assets/javascripts/supplier/app/controllers/index_controller.js.coffee +++ b/app/assets/javascripts/supplier/app/controllers/index_controller.js.coffee @@ -34,16 +34,19 @@ App.IndexController = Ember.ObjectController.extend toggleDashboardOrders: ->@set 'show_orders', !@get('show_orders') markOrderDelivered: (id)-> - $.post('/supplier/order_is_delivered', order_id: id) + #$.post('/supplier/order_is_delivered', order_id: id) + Ember.$.post Routes.mark_delivered_suppliers_order_path(id) if order = App.Order.findCached(id) order.set('state', 'delivered') markOrderActive: (id)-> - $.post('/supplier/mark_order_in_process', order_id: id) + #$.post('/supplier/mark_order_in_process', order_id: id) + Ember.$.post Routes.mark_in_process_suppliers_order_path(id) if order = App.Order.findCached(id) order.set('state', 'active') cancelOrder: (order)-> - $.post "/supplier/orders/#{order.id}/cancel" + #$.post "/supplier/orders/#{order.id}/cancel" + Ember.$.post Routes.cancel_suppliers_order_path(order.id) order.set 'state', 'cancelled' showList: (id)-> @transitionToRoute 'list', id diff --git a/app/assets/javascripts/supplier/app/helpers/can.js.coffee b/app/assets/javascripts/supplier/app/helpers/can.js.coffee index a9864afa..5f1680ac 100644 --- a/app/assets/javascripts/supplier/app/helpers/can.js.coffee +++ b/app/assets/javascripts/supplier/app/helpers/can.js.coffee @@ -1,5 +1,5 @@ Ember.Handlebars.registerHelper 'can', (operation, resource, options)-> - if operation is 'manage' and @get('controllers.application.employee_settings.manager') + if operation is 'manage' and @get('current_employee.manager') options.fn @ else options.inverse @ diff --git a/app/assets/javascripts/supplier/app/models/employee.js.coffee b/app/assets/javascripts/supplier/app/models/employee.js.coffee index bd8e3cdd..4b669a04 100644 --- a/app/assets/javascripts/supplier/app/models/employee.js.coffee +++ b/app/assets/javascripts/supplier/app/models/employee.js.coffee @@ -2,6 +2,8 @@ attr = DS.attr App.Employee= DS.Model.extend Ember.Validations.Mixin, name: attr 'string' email: attr 'string' + manager: attr 'boolean', defaultValue: false + active: attr 'boolean', defaultValue: true validations: name: {presence: true} diff --git a/app/assets/javascripts/supplier/app/models/list.js.coffee b/app/assets/javascripts/supplier/app/models/list.js.coffee index ccce380f..f280d5ca 100644 --- a/app/assets/javascripts/supplier/app/models/list.js.coffee +++ b/app/assets/javascripts/supplier/app/models/list.js.coffee @@ -45,11 +45,11 @@ App.List = DS.Model.extend ).property('state', 'orders.@each.state') close: -> @markClosed() - $.post Routes.supplier_close_list_path(), list_id: @id + $.post Routes.close_suppliers_list_pat(@id) is_helped: -> @markHelped() - $.post Routes.supplier_mark_list_as_helped_path(), list_id: @id + $.post Routes.mark_helped_suppliers_list_path(@id) remove_needs_payment: -> @set 'needs_payment', false $.post Routes.supplier_remove_list_needs_payment_path(), list_id: @id diff --git a/app/assets/javascripts/supplier/app/modifications/controller_modifications.js.coffee b/app/assets/javascripts/supplier/app/modifications/controller_modifications.js.coffee index 5c609fc9..4c473428 100644 --- a/app/assets/javascripts/supplier/app/modifications/controller_modifications.js.coffee +++ b/app/assets/javascripts/supplier/app/modifications/controller_modifications.js.coffee @@ -11,6 +11,7 @@ ControllerExtensions = Ember.Mixin.create @send "openModal", name, options all_sections: (-> @store.all('section')).property() + current_employee: (-> @get('controllers.application.employee') ).property('controllers.application.employee') Ember.Controller.reopen ControllerExtensions Ember.ArrayController.reopen ControllerExtensions diff --git a/app/assets/javascripts/supplier/app/routes/application_route.js.coffee.erb b/app/assets/javascripts/supplier/app/routes/application_route.js.coffee.erb index 56ab14c7..884b3e30 100644 --- a/app/assets/javascripts/supplier/app/routes/application_route.js.coffee.erb +++ b/app/assets/javascripts/supplier/app/routes/application_route.js.coffee.erb @@ -14,7 +14,6 @@ App.ApplicationRoute = Ember.Route.extend setupController: (controller)-> controller.set 'supplier', @supplier controller.set 'employee', @employee - controller.set 'employee_settings', Ember.Object.create(employee_settings) # @set 'supplier', @store.find('supplier', supplier_id) #controller.set 'sections', @sections #controller.set 'product_categories', @product_categories diff --git a/app/assets/javascripts/supplier/app/templates/global/_side_menu.emblem b/app/assets/javascripts/supplier/app/templates/global/_side_menu.emblem index 600eb0ac..7bd82820 100644 --- a/app/assets/javascripts/supplier/app/templates/global/_side_menu.emblem +++ b/app/assets/javascripts/supplier/app/templates/global/_side_menu.emblem @@ -2,14 +2,15 @@ aside.side-menu ul li.title: h3 Menu li.supplier-name= supplier.name - if supplier.open - li: a.supplier-close-shop{action "markSupplierClosed"}= t 'supplier.close_for_orders' - else - li: a.supplier-open-shop{action "markSupplierOpen"}= t 'supplier.open_for_orders' - li - =link-to 'settings' class="supplier-settings-link" - span.settings-icon - span= t 'supplier.settings' + can manage supplier + if supplier.open + li: a.supplier-close-shop{action "markSupplierClosed"}= t 'supplier.close_for_orders' + else + li: a.supplier-open-shop{action "markSupplierOpen"}= t 'supplier.open_for_orders' + li + =link-to 'settings' class="supplier-settings-link" + span.settings-icon + span= t 'supplier.settings' li class="supplier-sign-out-link" a{action "signOut"} span.sign-out-icon diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 0d82ea3c..b3ed4397 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -27,7 +27,7 @@ class DashboardController < ApplicationController if Rails.env.test? @tables = Table.all else - @tables = (current_supplier || Supplier.first).tables.sample(5) | List.active.map(&:table) | Supplier.find_by_email('supplier2@mozo.bar').tables.sample(3) + @tables = (Supplier.last || Supplier.first).tables.sample(5) | List.active.map(&:table) | Supplier.find_by_email('supplier2@mozo.bar').tables.sample(3) end respond_to do |format| format.html { render layout: 'phone' } diff --git a/app/controllers/supplier_controller.rb b/app/controllers/supplier_controller.rb index 8a5d3d6d..26f066e9 100644 --- a/app/controllers/supplier_controller.rb +++ b/app/controllers/supplier_controller.rb @@ -1,7 +1,4 @@ class SupplierController < Suppliers::ApplicationController - before_filter :setup_employee_and_supplier! - layout 'supplier/app' - def home end @@ -38,11 +35,11 @@ class SupplierController < Suppliers::ApplicationController def mark_as_open current_supplier.mark_as_open! - redirect_to :back + head :ok end def mark_as_closed current_supplier.mark_as_closed! - redirect_to :back + head :ok end # GET /suppliers/1/active_orders # GET /suppliers/1/active_orders.json @@ -97,20 +94,6 @@ class SupplierController < Suppliers::ApplicationController end end - # POST /supplier/close_list - def close_list - @list = List.find_by_supplier_id_and_id(current_supplier.id, params[:list_id]) - @list.close! - render nothing: true - end - - # POST /supplier/mark_list_as_helped - def mark_list_as_helped - @list = List.find_by_supplier_id_and_id(current_supplier.id, params[:list_id]) - @list.is_helped! - render nothing: true - end - #POST /supplier/remove_list_needs_payment def remove_list_needs_payment @list = List.find_by_supplier_id_and_id(current_supplier.id, params[:list_id]) @@ -118,20 +101,6 @@ class SupplierController < Suppliers::ApplicationController render nothing: true end - # POST /orders/1/is_being_processed - def mark_order_in_process - @order = Order.find_by_supplier_id_and_id!(current_supplier.id, params[:order_id]) - @order.is_being_processed! - render nothing: true - end - - # POST /orders/1/is_delivered - def order_is_delivered - @order = Order.find_by_supplier_id_and_id(current_supplier.id, params[:order_id]) - @order.is_delivered! - render nothing: true - end - private def supplier_params diff --git a/app/controllers/suppliers/application_controller.rb b/app/controllers/suppliers/application_controller.rb index 7c9a9e4e..a5e4f504 100644 --- a/app/controllers/suppliers/application_controller.rb +++ b/app/controllers/suppliers/application_controller.rb @@ -2,23 +2,26 @@ module Suppliers class ApplicationController < ::ApplicationController before_action :setup_employee_and_supplier! load_and_authorize_resource - attr_reader :current_supplier, :employee_settings - helper_method :current_supplier, :employee_settings + attr_reader :current_supplier + helper_method :current_supplier layout 'supplier/app' rescue_from 'RestClient::Conflict' do |e| #binding.pry end rescue_from CanCan::AccessDenied do |exception| - render json: {}, status: :forbidden + respond_to do |format| + format.html { redirect_to root_path, alert: 'Action forbidden'} + format.json { render json: {}, status: :forbidden } + end end def setup_employee_and_supplier! authenticate_employee! find_current_supplier! return unless current_supplier.present? - @employee_settings = current_supplier.employee_settings.for_employee( current_employee ) - @current_ability = ::Ability.new(@employee_settings) + current_employee.enrich_with_settings current_supplier.settings_for(current_employee) + @current_ability = ::Ability.new( current_employee ) end diff --git a/app/controllers/suppliers/lists_controller.rb b/app/controllers/suppliers/lists_controller.rb index dd116d0f..7172b16f 100644 --- a/app/controllers/suppliers/lists_controller.rb +++ b/app/controllers/suppliers/lists_controller.rb @@ -142,6 +142,19 @@ module Suppliers format.json { head :no_content } end end + # POST /supplier/lists/1/close + def close + @list = List.find_by_supplier_id_and_id(current_supplier.id, params[:id]) + @list.close! + head :ok + end + + # POST /supplier/lists/1/mark_helped + def mark_helped + @list = List.find_by_supplier_id_and_id(current_supplier.id, params[:id]) + @list.mark_helped! + head :ok + end private diff --git a/app/controllers/suppliers/orders_controller.rb b/app/controllers/suppliers/orders_controller.rb index 811e589f..5c5dc11e 100644 --- a/app/controllers/suppliers/orders_controller.rb +++ b/app/controllers/suppliers/orders_controller.rb @@ -27,5 +27,19 @@ module Suppliers format.json { render json: @order } end end + # POST /orders/1/mark_in_process + def mark_in_process + @order = Order.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) + @order.is_being_processed! + head :ok + end + + # POST /orders/1/is_delivered + def mark_delivered + @order = Order.find_by_supplier_id_and_id(current_supplier.id, params[:id]) + @order.is_delivered! + render nothing: true + end + end end diff --git a/app/models/employee.rb b/app/models/employee.rb index fba6135f..ce3067bf 100644 --- a/app/models/employee.rb +++ b/app/models/employee.rb @@ -1,6 +1,12 @@ class Employee include SimplyStored::Couch include ActiveModel::SerializerSupport + DEFAULT_SETTINGS = { + 'manager' => false, + 'active' => true + } + attr_accessor *DEFAULT_SETTINGS.keys + attr_reader :settings view :by_confirmation_token, key: :confirmation_token # devise confirmable devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable, :confirmable @@ -15,6 +21,9 @@ class Employee def count_by_email(email) database.view by_email(key: email, reduce: true) end + def default_settings + DEFAULT_SETTINGS + end end #validates :email, email: true @@ -22,4 +31,15 @@ class Employee has_many :orders has_and_belongs_to_many :lists, storing_keys: false + def enrich_with_settings(settings) + @settings = settings + settings.settings.each do |attribute, value| + public_send "#{attribute}=", value + end + settings + end + + def settings + @settings || SupplierEmployeesSettings.new(Supplier.new).for_employee(self) + end end diff --git a/app/models/list.rb b/app/models/list.rb index 5cb85323..15933655 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -150,7 +150,7 @@ class List set_price # should not be needed, but extra secure orders.map(&:close!) # close the connected orders self.state = 'closed' - self.is_helped! if needs_help? + self.mark_helped! if needs_help? self.needs_payment = false self.user_requests_closing = false # if a user requested closing, not needed anymore self.closed_at = Time.now @@ -173,7 +173,7 @@ class List end end - def is_helped! + def mark_helped! self.needs_help = false if save broadcast_users 'list_helped', id: id diff --git a/app/models/supplier.rb b/app/models/supplier.rb index ceb34d6e..e557187c 100644 --- a/app/models/supplier.rb +++ b/app/models/supplier.rb @@ -42,6 +42,11 @@ class Supplier has_many :sections, dependent: :destroy has_and_belongs_to_many :employees, storing_keys: true + alias_method :non_enriced_employees, :employees + def employees + non_enriced_employees.tap { |es| es.each{ |e| e.enrich_with_settings(settings_for(e) ) }} + end + after_create :add_section_on_create validates :name, presence: true @@ -66,7 +71,11 @@ class Supplier end def employee_settings - SupplierEmployeesSettings.new(self) + @employee_settings ||= SupplierEmployeesSettings.new(self) + end + + def settings_for(employee) + employee_settings.for_employee(employee) end def active_orders(options = {}) diff --git a/app/serializers/supplier_employees_settings.rb b/app/serializers/supplier_employees_settings.rb index af1170d8..f9941bec 100644 --- a/app/serializers/supplier_employees_settings.rb +++ b/app/serializers/supplier_employees_settings.rb @@ -2,7 +2,7 @@ class SupplierEmployeesSettings attr_reader :dictionary, :employee_ids, :supplier def initialize(supplier) @supplier = supplier - @dictionary = supplier.employee_settings_storage || {} + @dictionary = (supplier.employee_settings_storage || {}).to_h @employee_ids = supplier.employee_ids || [] end @@ -39,33 +39,92 @@ class SupplierEmployeesSettings self.replace options if options.is_a? Hash end + alias_method :orig_setter, :[]= def []=(*args) - super + orig_setter(*args) all_employees_settings.persist end end class SupplierEmployeeSettings delegate :as_json, :to_json, to: :settings - DEFAULTS = { - 'manager' => false - } attr_reader :id, :settings, :all_employees_settings class NullObject < ::NullObject + ::Employee::DEFAULT_SETTINGS.each do |attribute, value| + if value == true or value == false + define_method("#{attribute}?"){ value } + end + define_method(attribute){ value } + end end def initialize(all_employees_settings, employee_id, settings = {}) @all_employees_settings = all_employees_settings @id = employee_id - @settings = DEFAULTS.merge(settings || {}) + @settings = Employee.default_settings.merge(settings || {}) end - def manager? - settings['manager'] + def [](val) + settings[val.to_s] end - def is_manager! - all_employees_settings[id]['manager'] = true + def set(attribute, value, persist: false) + settings[attribute] = value + all_employees_settings[id][attribute] = value + if employee = all_employees_settings.supplier.employees.find{|e| e.id == id} + employee.public_send("#{attribute}=", value) + end + all_employees_settings.supplier.save if persist + self + end + + def []=(attribute, value) + set attribute, value + end + + def set!(attribute, value) + set attribute, value, persist: true + end + + # Parse a method name to its underlying operations + # settings.is_manager? + # is a getter for the attribute manager + # settings.is_manager! + # is a boolean setter to true for the attribute manager and persists the inderlying model + # without exclamation mark it is the same, but without persisting the model. + # settings.is_not_manager! + # is a boolean setter to false for the attribute manger. + # settings.manager + # is a normal accessor for the attribute manager + def parse_method_for_boolean_operation(method) + method = method.to_s + persist = false + attribute = method + set_value = nil + if method.end_with? '!' + persist = true + attribute.chop! + end + if method.end_with? '?' + # Always a getter, so no set_value + attribute.chop! + attribute = attribute.from(3) if attribute.start_with? 'is_' + elsif method.start_with? 'is_not_' + set_value = false + attribute = attribute.from 7 + elsif method.start_with? 'is_' + set_value = true + attribute = attribute.from 3 + end + raise "Settings do not support attribute '#{attribute}'" unless Employee.default_settings.has_key?(attribute) # Do not return a nonexistent attribute + [attribute, set_value, persist] + end + + def method_missing(m, *args) + attribute, set_value, persist = parse_method_for_boolean_operation(m) + return unless attribute # method cannot be used in the settings + return settings[attribute] if set_value.nil? # Getter operation, setting nil is not supported + set attribute, set_value, persist: persist end end end diff --git a/app/serializers/suppliers/employee_serializer.rb b/app/serializers/suppliers/employee_serializer.rb index ade9740c..fb67404e 100644 --- a/app/serializers/suppliers/employee_serializer.rb +++ b/app/serializers/suppliers/employee_serializer.rb @@ -1,5 +1,5 @@ class Suppliers::EmployeeSerializer < Qwaiter::Serializer self.root = :employee embed :ids, include: true - attributes :name, :email + attributes :name, :email, :manager, :active end diff --git a/app/services/ability.rb b/app/services/ability.rb index 631f517d..bf1b284b 100644 --- a/app/services/ability.rb +++ b/app/services/ability.rb @@ -1,11 +1,27 @@ class Ability + attr_reader :resource include CanCan::Ability - def initialize(settings) - settings ||= SupplierEmployeesSettings.new(Supplier.new).for_employee(nil) - if settings.manager? + def initialize(resource) + @resource = resource + case resource + when Employee then supplier_authorization + end + end + + def supplier_authorization + if resource.settings.manager? can :manage, :all + #cam :mark_as_open, Supplier else can :read, :all + can :qr_codes, Table + can :home, Supplier + can :current, :all + can :close, List + can :mark_helped, List + can :mark_in_process, Order + can :mark_delivered, Order + can :cancel, Order end end end diff --git a/app/views/suppliers/application/_head.html.erb b/app/views/suppliers/application/_head.html.erb index 89405cd9..eb616d49 100644 --- a/app/views/suppliers/application/_head.html.erb +++ b/app/views/suppliers/application/_head.html.erb @@ -2,8 +2,7 @@ //var $locale = '<%= I18n.locale %>'; //var supplier_id = '<%= current_supplier.id %>'; var supplier_object=<%= {id: current_supplier.id}.to_json.html_safe %>; -var employee_object=<%=raw current_employee.attributes.slice(:name, :email).merge(id: current_employee.id).to_json %>; -var employee_settings=<%= raw employee_settings.to_json %>; +var employee_object=<%=raw Suppliers::EmployeeSerializer.new(current_employee, root: false).to_json %>; var data_host = ''; var event_host = '<%= Qwaiter.event_host %>'; //var datepicker_options = {dateFormat: 'yy-mm-dd', firstDay: <%= current_supplier.week_starts_on_monday? ? 1 : 0 %>}; diff --git a/config/routes.rb b/config/routes.rb index 01adfc38..3af711b6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -104,12 +104,12 @@ Qwaiter::Application.routes.draw do get '/supplier/menu' => 'supplier#menu', as: :suppliers_menu #get '/supplier/lists/:list_id' => 'supplier#show_list', as: :supplier_show_list - post '/supplier/close_list' => 'supplier#close_list', as: :supplier_close_list - post '/supplier/mark_list_as_helped' => 'supplier#mark_list_as_helped', as: :supplier_mark_list_as_helped + #post '/supplier/close_list' => 'supplier#close_list', as: :supplier_close_list + #post '/supplier/mark_list_as_helped' => 'supplier#mark_list_as_helped', as: :supplier_mark_list_as_helped post '/supplier/remove_list_needs_payment' => 'supplier#remove_list_needs_payment', as: :supplier_remove_list_needs_payment - post '/supplier/mark_order_in_process' => 'supplier#mark_order_in_process', as: :supplier_mark_order_in_process - post '/supplier/order_is_delivered' => 'supplier#order_is_delivered', as: :supplier_order_is_delivered + #post '/supplier/mark_order_in_process' => 'supplier#mark_order_in_process', as: :supplier_mark_order_in_process + #post '/supplier/order_is_delivered' => 'supplier#order_is_delivered', as: :supplier_order_is_delivered post '/supplier/mark_as_open' => 'supplier#mark_as_open', as: :supplier_mark_as_open post '/supplier/mark_as_closed' => 'supplier#mark_as_closed', as: :supplier_mark_as_closed @@ -147,6 +147,8 @@ Qwaiter::Application.routes.draw do member do get :extra_info + post :mark_helped + post :close end end resources :product_categories do @@ -158,6 +160,8 @@ Qwaiter::Application.routes.draw do resources :orders, only: [:index, :show] do member do post :cancel + post :mark_in_process + post :mark_delivered end end root to: 'sections#index' diff --git a/spec/routing/supplier_routing_spec.rb b/spec/routing/supplier_routing_spec.rb index 210d5c28..49de56c2 100644 --- a/spec/routing/supplier_routing_spec.rb +++ b/spec/routing/supplier_routing_spec.rb @@ -18,9 +18,6 @@ describe SupplierController, type: :routing do it "routes to #mark_list_as_helped" do post("/supplier/mark_list_as_helped").should route_to("supplier#mark_list_as_helped") end - it "routes to #mark_order_in_process" do - post("/supplier/mark_order_in_process").should route_to("supplier#mark_order_in_process") - end it "routes to #order_is_delivered" do post("/supplier/order_is_delivered").should route_to("supplier#order_is_delivered") end