• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

foodcoops / foodsoft / 14290630730

06 Apr 2025 08:19AM UTC coverage: 44.865% (-23.3%) from 68.13%
14290630730

Pull #1078

github

web-flow
Merge c89532609 into 02853a526
Pull Request #1078: order balancing add group to article: sort ordergroup names alphabetically

3097 of 6903 relevant lines covered (44.86%)

14.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

15.63
/app/controllers/orders_controller.rb
1
#
2
# Controller for managing orders, i.e. all actions that require the "orders" role.
3
# Normal ordering actions of members of order groups is handled by the OrderingController.
4
class OrdersController < ApplicationController
1✔
5
  include Concerns::SendOrderPdf
1✔
6

7
  before_action :authenticate_pickups_or_orders
1✔
8
  before_action :authenticate_orders,
1✔
9
                except: %i[receive receive_on_order_article_create receive_on_order_article_update show]
10
  before_action :remove_empty_article, only: %i[create update]
1✔
11

12
  # List orders
13
  def index
1✔
14
    @open_orders = Order.open.includes(:supplier)
×
15
    @finished_orders = Order.finished_not_closed.includes(:supplier)
×
16
    @per_page = 15
×
17
    sort = if params['sort']
×
18
             case params['sort']
×
19
             when 'supplier'         then 'suppliers.name, ends DESC'
×
20
             when 'pickup'           then 'pickup DESC'
×
21
             when 'ends'             then 'ends DESC'
×
22
             when 'supplier_reverse' then 'suppliers.name DESC'
×
23
             when 'ends_reverse'     then 'ends'
×
24
             end
25
           else
26
             'ends DESC'
×
27
           end
28
    @suppliers = Supplier.having_articles.order('suppliers.name')
×
29
    @orders = Order.closed.includes(:supplier).reorder(sort).page(params[:page]).per(@per_page)
×
30
  end
31

32
  # Gives a view for the results to a specific order
33
  # Renders also the pdf
34
  def show
1✔
35
    @order = Order.find(params[:id])
×
36
    @view = (params[:view] || 'default').gsub(/[^-_a-zA-Z0-9]/, '')
×
37
    @partial = case @view
×
38
               when 'default'  then 'articles'
×
39
               when 'groups'   then 'shared/articles_by/groups'
×
40
               when 'articles' then 'shared/articles_by/articles'
×
41
               else 'articles'
×
42
               end
43

44
    respond_to do |format|
×
45
      format.html
×
46
      format.js do
×
47
        render layout: false
×
48
      end
49
      format.pdf do
×
50
        send_order_pdf @order, params[:document]
×
51
      end
52
      format.csv do
×
53
        send_data OrderCsv.new(@order).to_csv, filename: @order.name + '.csv', type: 'text/csv'
×
54
      end
55
      format.text do
×
56
        send_data OrderTxt.new(@order).to_txt, filename: @order.name + '.txt', type: 'text/plain'
×
57
      end
58
    end
59
  end
60

61
  # Page to create a new order.
62
  def new
1✔
63
    if params[:order_id]
×
64
      old_order = Order.find(params[:order_id])
×
65
      @order = Order.new(supplier_id: old_order.supplier_id).init_dates
×
66
      @order.article_ids = old_order.article_ids
×
67
    else
68
      @order = Order.new(supplier_id: params[:supplier_id]).init_dates
×
69
    end
70
  rescue StandardError => e
71
    redirect_to orders_url, alert: t('errors.general_msg', msg: e.message)
×
72
  end
73

74
  # Page to edit an exsiting order.
75
  # editing finished orders is done in FinanceController
76
  def edit
1✔
77
    @order = Order.includes(:articles).find(params[:id])
×
78
  end
79

80
  # Save a new order.
81
  # order_articles will be saved in Order.article_ids=()
82
  def create
1✔
83
    @order = Order.new(params[:order])
×
84
    @order.created_by = current_user
×
85
    @order.updated_by = current_user
×
86
    if @order.save
×
87
      flash[:notice] = I18n.t('orders.create.notice')
×
88
      redirect_to @order
×
89
    else
90
      logger.debug "[debug] order errors: #{@order.errors.messages}"
×
91
      render action: 'new'
×
92
    end
93
  end
94

95
  # Update an existing order.
96
  def update
1✔
97
    @order = Order.find params[:id]
×
98
    if @order.update params[:order].merge(updated_by: current_user)
×
99
      flash[:notice] = I18n.t('orders.update.notice')
×
100
      redirect_to action: 'show', id: @order
×
101
    else
102
      render action: 'edit'
×
103
    end
104
  end
105

106
  # Delete an order.
107
  def destroy
1✔
108
    Order.find(params[:id]).destroy
×
109
    redirect_to action: 'index'
×
110
  end
111

112
  # Finish a current order.
113
  def finish
1✔
114
    order = Order.find(params[:id])
×
115
    order.finish!(@current_user)
×
116
    redirect_to order, notice: I18n.t('orders.finish.notice')
×
117
  rescue StandardError => e
118
    redirect_to orders_url, alert: I18n.t('errors.general_msg', msg: e.message)
×
119
  end
120

121
  # Send a order to the supplier.
122
  def send_result_to_supplier
1✔
123
    order = Order.find(params[:id])
×
124
    order.send_to_supplier!(@current_user)
×
125
    redirect_to order, notice: I18n.t('orders.send_to_supplier.notice')
×
126
  rescue StandardError => e
127
    redirect_to order, alert: I18n.t('errors.general_msg', msg: e.message)
×
128
  end
129

130
  def receive
1✔
131
    @order = Order.find(params[:id])
×
132
    if request.post?
×
133
      Order.transaction do
×
134
        s = update_order_amounts
×
135
        @order.update_attribute(:state, 'received') if @order.state != 'received'
×
136

137
        flash[:notice] = (s ? I18n.t('orders.receive.notice', msg: s) : I18n.t('orders.receive.notice_none'))
×
138
      end
139
      NotifyReceivedOrderJob.perform_later(@order)
×
140
      if current_user.role_orders? || current_user.role_finance?
×
141
        redirect_to @order
×
142
      elsif current_user.role_pickups?
×
143
        redirect_to pickups_path
×
144
      else
145
        redirect_to receive_order_path(@order)
×
146
      end
147
    else
148
      @order_articles = @order.order_articles.ordered_or_member.includes(:article_version).order('article_versions.order_number, article_versions.name')
×
149
    end
150
  end
151

152
  def receive_on_order_article_create # See publish/subscribe design pattern in /doc.
1✔
153
    @order_article = OrderArticle.find(params[:order_article_id])
×
154
    render layout: false
×
155
  end
156

157
  def receive_on_order_article_update # See publish/subscribe design pattern in /doc.
1✔
158
    @order_article = OrderArticle.find(params[:order_article_id])
×
159
    render layout: false
×
160
  end
161

162
  protected
1✔
163

164
  def update_order_amounts
1✔
165
    return unless params[:order_articles]
×
166

167
    # where to leave remainder during redistribution
168
    rest_to = []
×
169
    rest_to << :tolerance if params[:rest_to_tolerance]
×
170
    rest_to << :stock if params[:rest_to_stock]
×
171
    rest_to << nil
×
172
    # count what happens to the articles:
173
    #   changed, rest_to_tolerance, rest_to_stock, left_over
174
    counts = [0] * 4
×
175
    cunits = [0] * 4
×
176
    # This was once wrapped in a transaction, but caused
177
    # "MySQL lock timeout exceeded" errors. It's ok to do
178
    # this article-by-article anway.
179
    params[:order_articles].each do |oa_id, oa_params|
×
180
      next if oa_params.blank?
×
181

182
      oa = OrderArticle.find(oa_id)
×
183
      # update attributes; don't use update_attribute because it calls save
184
      # which makes received_changed? not work anymore
185
      oa.attributes = oa_params
×
186
      if oa.units_received_changed?
×
187
        counts[0] += 1
×
188
        if oa.units_received.present?
×
189
          units_received = oa.article_version.convert_quantity(oa.units_received,
×
190
                                                               oa.article_version.supplier_order_unit, oa.article_version.group_order_unit)
191
          cunits[0] += units_received
×
192
          oacounts = oa.redistribute units_received, rest_to
×
193
          oacounts.each_with_index do |c, i|
×
194
            cunits[i + 1] += c
×
195
            counts[i + 1] += 1 if c > 0
×
196
          end
197
        end
198
      end
199
      oa.save!
×
200
    end
201
    return nil if counts[0] == 0
×
202

203
    notice = []
×
204
    notice << I18n.t('orders.update_order_amounts.msg1', count: counts[0], units: cunits[0])
×
205
    if params[:rest_to_tolerance]
×
206
      notice << I18n.t('orders.update_order_amounts.msg2', count: counts[1],
×
207
                                                           units: cunits[1])
208
    end
209
    notice << I18n.t('orders.update_order_amounts.msg3', count: counts[2], units: cunits[2]) if params[:rest_to_stock]
×
210
    if counts[3] > 0 || cunits[3] > 0
×
211
      notice << I18n.t('orders.update_order_amounts.msg4', count: counts[3],
×
212
                                                           units: cunits[3])
213
    end
214
    notice.join(', ')
×
215
  end
216

217
  def remove_empty_article
1✔
218
    params[:order][:article_ids].reject!(&:blank?) if params[:order] && params[:order][:article_ids]
×
219
  end
220
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc