Skip to content

Commit

Permalink
Merge pull request #373 from foodcoops/feature/current-orders-plugin
Browse files Browse the repository at this point in the history
Add current_orders plugin
  • Loading branch information
wvengen committed Aug 7, 2015
2 parents a0fa523 + cb000a0 commit 4a9cf86
Show file tree
Hide file tree
Showing 47 changed files with 1,093 additions and 13 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ gem 'foodsoft_wiki', path: 'plugins/wiki'
gem 'foodsoft_messages', path: 'plugins/messages'

# plugins not enabled by default
#gem 'foodsoft_current_orders', path: 'plugins/current_orders'
#gem 'foodsoft_uservoice', path: 'plugins/uservoice'


Expand Down
9 changes: 6 additions & 3 deletions app/documents/order_by_articles.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ def body
rows << [goa.group_order.ordergroup.name,
"#{goa.quantity} + #{goa.tolerance}",
goa.result,
number_with_precision(order_article.price.fc_price * goa.result, precision: 2)]
number_to_currency(goa.total_price(order_article))]
dimrows << rows.length if goa.result == 0
end
next if rows.length == 0
rows.unshift I18n.t('documents.order_by_articles.rows') # table header

text "#{order_article.article.name} (#{order_article.article.unit} | #{order_article.price.unit_quantity.to_s} | #{number_with_precision(order_article.price.fc_price, precision: 2)})",
text "#{order_article.article.name} (#{order_article.article.unit} | #{order_article.price.unit_quantity.to_s} | #{number_to_currency(order_article.price.fc_price)})",
style: :bold, size: fontsize(10)
table rows, cell_style: {size: fontsize(8), overflow: :shrink_to_fit} do |table|
table.column(0).width = 200
Expand All @@ -36,7 +36,10 @@ def body
table.cells.border_color = '666666'
table.rows(0).border_bottom_width = 2
# dim rows which were ordered but not received
dimrows.each { |ri| table.row(ri).text_color = '999999' }
dimrows.each do |ri|
table.row(ri).text_color = '999999'
table.row(ri).columns(0..-1).font_style = nil
end
end
end
end
Expand Down
27 changes: 17 additions & 10 deletions app/documents/order_by_groups.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,30 @@ def body
sub_total = price * goa.result
total += sub_total
rows << [goa.order_article.article.name,
"#{goa.quantity} + #{goa.tolerance}",
goa.tolerance > 0 ? "#{goa.quantity} + #{goa.tolerance}" : goa.quantity,
goa.result,
number_with_precision(price, precision: 2),
number_to_currency(price),
goa.order_article.price.unit_quantity,
goa.order_article.article.unit,
number_with_precision(sub_total, precision: 2)]
number_to_currency(sub_total)]
dimrows << rows.length if goa.result == 0
end
next if rows.length == 0
rows << [ I18n.t('documents.order_by_groups.sum'), nil, nil, nil, nil, nil, number_with_precision(total, precision: 2)]
rows << [ I18n.t('documents.order_by_groups.sum'), nil, nil, nil, nil, nil, number_to_currency(total)]
rows.unshift I18n.t('documents.order_by_groups.rows') # Table Header

text group_order.ordergroup.name, size: fontsize(9), style: :bold
table rows, width: 500, cell_style: {size: fontsize(8), overflow: :shrink_to_fit} do |table|
# borders
table.cells.borders = []
table.row(0).borders = [:bottom]
table.row(group_order_articles.size).borders = [:bottom]
table.cells.border_width = 1
table.cells.border_color = '666666'
table.cells.borders = [:bottom]
table.cells.border_width = 0.02
table.cells.border_color = 'dddddd'
table.rows(0).border_width = 1
table.rows(0).border_color = '666666'
table.rows(0).column(5).font_style = :bold
table.row(rows.length-2).border_width = 1
table.row(rows.length-2).border_color = '666666'
table.row(rows.length-1).borders = []

table.column(0).width = 240
table.column(2).font_style = :bold
Expand All @@ -53,7 +57,10 @@ def body
table.column(6).font_style = :bold

# dim rows which were ordered but not received
dimrows.each { |ri| table.row(ri).text_color = '999999' }
dimrows.each do |ri|
table.row(ri).text_color = '999999'
table.row(ri).columns(0..-1).font_style = nil
end
end
end

Expand Down
1 change: 1 addition & 0 deletions config/locales/nl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1680,6 +1680,7 @@ nl:
title_all: Alle groepstaken
ui:
actions: Acties
back: Terug
cancel: Annuleren
close: Sluiten
copy: Kopiëren
Expand Down
42 changes: 42 additions & 0 deletions plugins/current_orders/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
FoodsoftCurrentOrders
=====================

Foodsoft is currently designed to work with one order at a time. In practice,
however there can be multiple orders open at the same time, with one pickup
day. The proper solution to this is to introduce the notion of order cycles,
with each order belonging to a cycle. Until that time, we have this plugin,
with screens for working on all orders that are closed-but-not-finished.

Important: be sure to settle orders from the previous order cycle, before
you close any. If you don't, articles from previous and current dates start
to mix up (if you do, settle the old ones asap).

* `current_orders/orders/receive` for a list of orders that can be received.
* `current_orders/orders.pdf?document=(groups|articles)` for PDFs for all
orders that are closed but not settled.
* `current_orders/articles` to edit an order article's ordergroups in all
orders that are closed but not settled.
* `current_orders/ordergroups` to edit an ordergroup's order articles in all
orders that are closed but not settled.
* `current_orders/group_orders` for all articles in the user's group orders
from orders that are not settled. Can be used as a "shopping-cart overview"
or "checkout" page.

New menu items will be added in the "Orders" menu. Please note that members
with _Orders_ permission will now be able to edit the amounts members received
in some of these screens, something that was previously restricted to the
_Finance_ permission.

This plugin is not enabled by default. To install it, add uncomment the
corresponding line in the `Gemfile`, or add:

```Gemfile
gem 'foodsoft_current_orders', path: 'plugins/current_orders'
```

This plugin introduces the foodcoop config option `use_current_orders`, which
needs to be set to `true` to enable the plugin. This can be done in the
configuration screen or `config/app_config.yml`.

This plugin is part of the foodsoft package and uses the GPL-3 license or later
(see foodsoft's LICENSE for the full license text).
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# encoding: utf-8
class CurrentOrders::ArticlesController < ApplicationController

before_filter :authenticate_orders
before_filter :find_order_and_order_article, only: [:index, :show]

def index
# sometimes need to pass id as parameter for forms
show if @order_article
end

def show
respond_to do |format|
format.html { render :show }
format.js { render :show, layout: false }
end
end

def show_on_group_order_article_create
@goa = GroupOrderArticle.find(params[:group_order_article_id])
end

def show_on_group_order_article_update
#@goa = GroupOrderArticle.find(params[:group_order_article_id])
end

protected

def find_order_and_order_article
@current_orders = Order.finished_not_closed
unless params[:order_id].blank?
@order = Order.find(params[:order_id])
@order_articles = @order.order_articles
else
@order_articles = OrderArticle.where(order_id: @current_orders.all.map(&:id))
end
@q = OrderArticle.search(params[:q])
@order_articles = @order_articles.ordered.merge(@q.result).includes(:article, :article_price)
@order_article = @order_articles.where(id: params[:id]).first
end

helper_method \
def ordergroups_for_adding
Ordergroup.undeleted.order(:name)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class CurrentOrders::GroupOrdersController < ApplicationController
# Security
before_filter :ensure_ordergroup_member

def index
# XXX code duplication lib/foodsoft_current_orders/app/controllers/current_orders/ordergroups_controller.rb
@order_ids = Order.where(state: ['open', 'finished']).all.map(&:id)
@goas = GroupOrderArticle.includes(:group_order => :ordergroup).includes(:order_article).
where(group_orders: {order_id: @order_ids, ordergroup_id: @ordergroup.id}).ordered
@articles_grouped_by_category = @goas.includes(:order_article => {:article => :article_category}).
order('articles.name').
group_by { |a| a.order_article.article.article_category.name }.
sort { |a, b| a[0] <=> b[0] }
end

private

# XXX code duplication from GroupOrdersController
def ensure_ordergroup_member
@ordergroup = @current_user.ordergroup
if @ordergroup.nil?
redirect_to root_url, :alert => I18n.t('group_orders.errors.no_member')
end
end

end
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# encoding: utf-8
class CurrentOrders::OrdergroupsController < ApplicationController

before_filter :authenticate_orders
before_filter :find_group_orders, only: [:index, :show]

def index
# sometimes need to pass id as parameter for forms
render 'show' if @ordergroup
end

def show
respond_to do |format|
format.html { render :show }
format.js { render :show, layout: false }
end
end

def show_on_group_order_article_create
@goa = GroupOrderArticle.find(params[:group_order_article_id])
end

def show_on_group_order_article_update
#@goa = GroupOrderArticle.find(params[:group_order_article_id])
@group_order = GroupOrder.find(params[:group_order_id])
@ordergroup = @group_order.ordergroup
end

protected

def find_group_orders
@order_ids = Order.finished_not_closed.map(&:id)

@all_ordergroups = Ordergroup.undeleted.order(:name).to_a
@ordered_group_ids = GroupOrder.where(order_id: @order_ids).pluck('DISTINCT(ordergroup_id)')
@all_ordergroups.sort_by! {|o| @ordered_group_ids.include?(o.id) ? o.name : "ZZZZZ#{o.name}" }

@ordergroup = Ordergroup.find(params[:id]) unless params[:id].nil?
@goas = GroupOrderArticle.includes(:group_order, :order_article => [:article, :article_price]).
where(group_orders: {order_id: @order_ids, ordergroup_id: @ordergroup.id}).ordered.all unless @ordergroup.nil?
end

helper_method \
def articles_for_adding
OrderArticle.includes(:article, :article_price).where(order_id: @order_ids)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class CurrentOrders::OrdersController < ApplicationController

before_filter :authenticate_orders, except: :my

def show
@doc_options ||= {}
@order_ids = if params[:id]
params[:id].split('+').map(&:to_i)
else
Order.finished_not_closed.all.map(&:id)
end
@view = (params[:view] or 'default').gsub(/[^-_a-zA-Z0-9]/, '')

respond_to do |format|
format.pdf do
pdf = case params[:document]
when 'groups' then MultipleOrdersByGroups.new(@order_ids, @doc_options)
when 'articles' then MultipleOrdersByArticles.new(@order_ids, @doc_options)
end
send_data pdf.to_pdf, filename: pdf.filename, type: 'application/pdf'
end
end
end

def my
@doc_options ||= {}
@doc_options[:ordergroup] = @current_user.ordergroup.id
respond_to do |format|
format.pdf do
params[:document] = 'groups'
show
end
end
end

def receive
@orders = Order.finished_not_closed.includes(:supplier)
end

end
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# encoding: utf-8
class CurrentOrdersController < ApplicationController

before_filter :authenticate_orders

end
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# encoding: utf-8
class MultipleOrdersByArticles < OrderPdf
include OrdersHelper

def filename
I18n.t('documents.multiple_orders_by_articles.filename', count: @order.count) + '.pdf'
end

def title
I18n.t('documents.multiple_orders_by_articles.title', count: @order.count)
end

def order_articles
@order_articles ||= OrderArticle.joins(:order, :article).where(:orders => {:id => @order}).ordered.reorder('orders.id, articles.name')
end

# @todo refactor to reduce common code with order_by_articles
def body
order_articles.each do |order_article|
down_or_page

rows = []
dimrows = []
has_units_str = ''
for goa in order_article.group_order_articles.ordered
rows << [goa.group_order.ordergroup.name,
goa.tolerance > 0 ? "#{goa.quantity} + #{goa.tolerance}" : goa.quantity,
goa.result,
number_to_currency(goa.total_price(order_article))]
dimrows << rows.length if goa.result == 0
end
next if rows.length == 0
sum = order_article.group_orders_sum
rows.unshift I18n.t('documents.order_by_articles.rows').dup # table header

rows << [I18n.t('documents.order_by_groups.sum'),
order_article.tolerance > 0 ? "#{order_article.quantity} + #{order_article.tolerance}" : order_article.quantity,
sum[:quantity],
nil] #number_to_currency(sum[:price])]

text "<b>#{order_article.article.name}</b> " +
"(#{order_article.article.unit}; #{number_to_currency order_article.price.fc_price}; " +
units_history_line(order_article, plain: true) + ')',
size: fontsize(10), inline_format: true
table rows, cell_style: {size: fontsize(8), overflow: :shrink_to_fit} do |table|
# borders
table.cells.borders = [:bottom]
table.cells.border_width = 0.02
table.cells.border_color = 'dddddd'
table.rows(0).border_width = 1
table.rows(0).border_color = '666666'
table.row(rows.length-2).border_width = 1
table.row(rows.length-2).border_color = '666666'
table.row(rows.length-1).borders = []

table.column(0).width = 200
table.columns(1..2).align = :center
table.column(2).font_style = :bold
table.columns(3).align = :right

# dim rows which were ordered but not received
dimrows.each { |ri| table.row(ri).text_color = '999999' }
end
end
end

protected

def pdf_add_page_breaks?
super 'order_by_articles'
end

end
Loading

0 comments on commit 4a9cf86

Please sign in to comment.