Skip to content

Commit

Permalink
API v1 group_order_articles endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
wvengen committed Nov 4, 2018
1 parent f0b8bfc commit cae9e70
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 15 deletions.
100 changes: 100 additions & 0 deletions app/controllers/api/v1/group_order_articles_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
class Api::V1::GroupOrderArticlesController < Api::V1::BaseController
include Concerns::CollectionScope

before_action :require_ordergroup
before_action :require_minimum_balance, only: [:create, :update] # destroy is ok
before_action :require_enough_apples, only: [:create, :update] # destroy is ok
# @todo allow decreasing amounts when minimum balance isn't met

def index
render_collection search_scope
end

def show
goa = scope.find(params.require(:id))
render_goa_with_oa(goa)
end

def create
goa = nil
GroupOrderArticle.transaction do
oa = order_articles_scope.find(create_params.require(:order_article_id))
go = current_ordergroup.group_orders.find_or_create_by!(order_id: oa.order_id)
goa = go.group_order_articles.create!(order_article: oa)
goa.update_quantities((create_params[:quantity] || 0).to_i, (create_params[:tolerance] || 0).to_i)
oa.update_results!
go.update_price!
end
render_goa_with_oa(goa)
end

def update
goa = nil
GroupOrderArticle.transaction do
goa = scope.includes(:group_order_article_quantities).find(params.require(:id))
goa.update_quantities((update_params[:quantity] || goa.quantity).to_i, (update_params[:tolerance] || goa.tolerance).to_i)
goa.order_article.update_results!
goa.group_order.update_price!
end
render_goa_with_oa(goa)
end

def destroy
goa = nil
GroupOrderArticle.transaction do
goa = scope.find(params.require(:id))
goa.destroy!
goa.order_article.update_results!
goa.group_order.update_price!
end
render_goa_with_oa(nil, goa.order_article)
end

private

def max_per_page
nil
end

def scope
GroupOrderArticle.
includes(order_article: :article).
joins(group_order: :order).
where(group_orders: { ordergroup_id: current_ordergroup.id }).
merge(Order.open)
end

def order_articles_scope
OrderArticle.joins(:order).merge(Order.open)
end

def create_params
params.require(:group_order_article).permit(:order_article_id, :quantity, :tolerance)
end

def update_params
params.require(:group_order_article).permit(:quantity, :tolerance)
end

def require_minimum_balance
minimum_balance = FoodsoftConfig[:minimum_balance] or return
if current_ordergroup.account_balance < minimum_balance
raise Api::Errors::PermissionRequired.new(t('application.controller.error_minimum_balance', min: minimum_balance))
end
end

def require_enough_apples
if current_ordergroup.not_enough_apples?
s = t('group_orders.messages.not_enough_apples', apples: current_ordergroup.apples, stop_ordering_under: FoodsoftConfig[:stop_ordering_under])
raise Api::Errors::PermissionRequired.new(s)
end
end

def render_goa_with_oa(goa, oa = goa.order_article)
data = {}
data[:group_order_article] = GroupOrderArticleSerializer.new(goa) if goa
data[:order_article] = OrderArticleSerializer.new(oa) if oa

render json: data, root: nil
end
end
8 changes: 8 additions & 0 deletions app/models/group_order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ class GroupOrder < ActiveRecord::Base

scope :ordered, -> { includes(:ordergroup).order('groups.name') }

def self.ransackable_attributes(auth_object = nil)
%w(id price)
end

def self.ransackable_associations(auth_object = nil)
%w(order group_order_articles)
end

# Generate some data for the javascript methods in ordering view
def load_data
data = {}
Expand Down
13 changes: 11 additions & 2 deletions app/models/group_order_article.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,24 @@ class GroupOrderArticle < ActiveRecord::Base

belongs_to :group_order
belongs_to :order_article
has_many :group_order_article_quantities, :dependent => :destroy
has_many :group_order_article_quantities, dependent: :destroy

validates_presence_of :group_order, :order_article
validates_uniqueness_of :order_article_id, :scope => :group_order_id # just once an article per group order
validates :quantity, :tolerance, numericality: {only_integer: true, greater_than_or_equal_to: 0}

scope :ordered, -> { includes(:group_order => :ordergroup).order('groups.name') }

localize_input_of :result

def self.ransackable_attributes(auth_object = nil)
%w(id quantity tolerance result)
end

def self.ransackable_associations(auth_object = nil)
%w(order_article group_order)
end

# Setter used in group_order_article#new
# We have to create an group_order, if the ordergroup wasn't involved in the order yet
def ordergroup_id=(id)
Expand Down Expand Up @@ -85,7 +94,7 @@ def update_quantities(quantity, tolerance)

# Check if something went terribly wrong and quantites have not been adjusted as desired.
if (self.quantity != quantity || self.tolerance != tolerance)
raise 'Invalid state: unable to update GroupOrderArticle/-Quantities to desired quantities!'
raise ActiveRecord::RecordNotSaved.new('Unable to update GroupOrderArticle/-Quantities to desired quantities!', self)
end

# Remove zero-only items.
Expand Down
12 changes: 6 additions & 6 deletions app/models/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ class Order < ActiveRecord::Base
after_save :save_order_articles, :update_price_of_group_orders

# Finders
scope :open, -> { where(state: 'open').order('ends DESC') }
scope :finished, -> { where("orders.state = 'finished' OR orders.state = 'closed'").order('ends DESC') }
scope :finished_not_closed, -> { where(state: 'finished').order('ends DESC') }
scope :closed, -> { where(state: 'closed').order('ends DESC') }
scope :stockit, -> { where(supplier_id: 0).order('ends DESC') }
scope :recent, -> { order('starts DESC').limit(10) }
scope :open, -> { where(state: 'open').order('orders.ends DESC') }
scope :finished, -> { where("orders.state = 'finished' OR orders.state = 'closed'").order('orders.ends DESC') }
scope :finished_not_closed, -> { where(state: 'finished').order('orders.ends DESC') }
scope :closed, -> { where(state: 'closed').order('orders.ends DESC') }
scope :stockit, -> { where(supplier_id: 0).order('orders.ends DESC') }
scope :recent, -> { order('orders.starts DESC').limit(10) }
scope :stock_group_order, -> { group_orders.where(ordergroup_id: nil).first }

# Allow separate inputs for date and time
Expand Down
14 changes: 7 additions & 7 deletions app/models/ordergroup.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# encoding: utf-8
#
# Ordergroups can order, they are "children" of the class Group
#
#
# Ordergroup have the following attributes, in addition to Group
# * account_balance (decimal)
class Ordergroup < Group
Expand All @@ -13,7 +13,8 @@ class Ordergroup < Group

has_many :financial_transactions
has_many :group_orders
has_many :orders, :through => :group_orders
has_many :group_order_articles, through: :group_orders
has_many :orders, through: :group_orders

validates_numericality_of :account_balance, :message => I18n.t('ordergroups.model.invalid_balance')
validate :uniqueness_of_name, :uniqueness_of_members
Expand Down Expand Up @@ -54,7 +55,7 @@ def last_order
def value_of_open_orders(exclude = nil)
group_orders.in_open_orders.reject{|go| go == exclude}.collect(&:price).sum
end

def value_of_finished_orders(exclude = nil)
group_orders.in_finished_orders.reject{|go| go == exclude}.collect(&:price).sum
end
Expand Down Expand Up @@ -94,7 +95,7 @@ def avg_jobs_per_euro
stats[:jobs_size].to_f / stats[:orders_sum].to_f rescue 0
end

# This is the ordergroup job per euro performance
# This is the ordergroup job per euro performance
# in comparison to the hole foodcoop average
def apples
((avg_jobs_per_euro / Ordergroup.avg_jobs_per_euro) * 100).to_i rescue 0
Expand Down Expand Up @@ -122,7 +123,7 @@ def self.avg_jobs_per_euro
def account_updated
financial_transactions.last.try(:created_on) || created_on
end

private

# Make sure, that a user can only be in one ordergroup
Expand All @@ -141,6 +142,5 @@ def uniqueness_of_name
errors.add :name, message
end
end

end

end
9 changes: 9 additions & 0 deletions app/serializers/group_order_article_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class GroupOrderArticleSerializer < ActiveModel::Serializer
attributes :id, :order_article_id
attributes :quantity, :tolerance, :result, :total_price

def total_price
# make sure BigDecimal is serialized as a number
object.total_price.to_f
end
end
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ en:
error_denied_sign_in: sign in as another user
error_feature_disabled: This feature is currently disabled.
error_members_only: This action is only available to members of the group!
error_minimum_balance: Sorry, your account balance is below the minimum of %{min}.
error_token: Access denied (invalid token)!
article_categories:
create:
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@
resources :financial_transactions, only: [:index, :show]
resources :orders, only: [:index, :show]
resources :order_articles, only: [:index, :show]
resources :group_order_articles
end
end

Expand Down

0 comments on commit cae9e70

Please sign in to comment.