Merge pull request #387 from foodcoops/feature/boxfills
Add optional boxfill phase to orders (+ bootstrap buttons)
This commit is contained in:
commit
227ca0dd84
16 changed files with 271 additions and 76 deletions
|
|
@ -5,20 +5,20 @@
|
|||
//
|
||||
// Call setDecimalSeparator(char) to overwrite the default character "." with a localized value.
|
||||
|
||||
var modified = false // indicates if anything has been clicked on this page
|
||||
var groupBalance = 0; // available group money
|
||||
var minimumBalance = 0; // minimum group balance for the order to be succesful
|
||||
var modified = false; // indicates if anything has been clicked on this page
|
||||
var groupBalance = 0; // available group money
|
||||
var minimumBalance = 0; // minimum group balance for the order to be succesful
|
||||
var toleranceIsCostly = true; // default tolerance behaviour
|
||||
var isStockit = false; // Wheter the order is from stock oder normal supplier
|
||||
var isStockit = false; // Whether the order is from stock oder normal supplier
|
||||
|
||||
// Article data arrays:
|
||||
var price = new Array();
|
||||
var unit = new Array(); // items per order unit
|
||||
var itemTotal = new Array(); // total item price
|
||||
var unit = new Array(); // items per order unit
|
||||
var itemTotal = new Array(); // total item price
|
||||
var quantityOthers = new Array();
|
||||
var toleranceOthers = new Array();
|
||||
var itemsAllocated = new Array(); // how many items the group has been allocated and should definitely get
|
||||
var quantityAvailable = new Array(); // stock_order. how many items are currently in stock
|
||||
var itemsAllocated = new Array(); // how many items the group has been allocated and should definitely get
|
||||
var quantityAvailable = new Array(); // stock_order. how many items are currently in stock
|
||||
|
||||
function setToleranceBehaviour(value) {
|
||||
toleranceIsCostly = value;
|
||||
|
|
@ -48,27 +48,37 @@ function addData(orderArticleId, itemPrice, itemUnit, itemSubtotal, itemQuantity
|
|||
}
|
||||
|
||||
function increaseQuantity(item) {
|
||||
var value = Number($('#q_' + item).val()) + 1;
|
||||
var $el = $('#q_' + item),
|
||||
value = Number($el.val()) + 1,
|
||||
max = $el.data('max');
|
||||
if (value > max) { value = max; }
|
||||
if (!isStockit || (value <= (quantityAvailable[item] + itemsAllocated[item]))) {
|
||||
update(item, value, $('#t_' + item).val());
|
||||
}
|
||||
}
|
||||
|
||||
function decreaseQuantity(item) {
|
||||
var value = Number($('#q_' + item).val()) - 1;
|
||||
if (value >= 0) {
|
||||
var $el = $('#q_' + item),
|
||||
value = Number($el.val()) - 1,
|
||||
min = $el.data('min') || 0;
|
||||
if (value >= min) {
|
||||
update(item, value, $('#t_' + item).val());
|
||||
}
|
||||
}
|
||||
|
||||
function increaseTolerance(item) {
|
||||
var value = Number($('#t_' + item).val()) + 1;
|
||||
var $el = $('#t_' + item),
|
||||
value = Number($el.val()) + 1;
|
||||
max = $el.data('max');
|
||||
if (value > max) { value = max; }
|
||||
update(item, $('#q_' + item).val(), value);
|
||||
}
|
||||
|
||||
function decreaseTolerance(item) {
|
||||
var value = Number($('#t_' + item).val()) - 1;
|
||||
if (value >= 0) {
|
||||
var $el = $('#t_' + item),
|
||||
value = Number($el.val()) - 1,
|
||||
min = $el.data('min') || 0;
|
||||
if (value >= min) {
|
||||
update(item, $('#q_' + item).val(), value);
|
||||
}
|
||||
}
|
||||
|
|
@ -139,9 +149,8 @@ function update(item, quantity, tolerance) {
|
|||
.removeClass('missing-many missing-few missing-none')
|
||||
.addClass(missing_units_css);
|
||||
|
||||
|
||||
// update balance
|
||||
updateBalance();
|
||||
updateButtons($('#q_'+item).closest('tr'));
|
||||
}
|
||||
|
||||
function calcUnits(unitSize, quantity, tolerance) {
|
||||
|
|
@ -184,21 +193,43 @@ function updateBalance() {
|
|||
}
|
||||
}
|
||||
|
||||
function updateButtons($el) {
|
||||
// enable/disable buttons depending on min/max vs. value
|
||||
$el.find('a[data-increase_quantity]').each(function() {
|
||||
var $q = $el.find('#q_'+$(this).data('increase_quantity'));
|
||||
$(this).toggleClass('disabled', $q.val() >= $q.data('max'));
|
||||
});
|
||||
$el.find('a[data-decrease_quantity]').each(function() {
|
||||
var $q = $el.find('#q_'+$(this).data('decrease_quantity'));
|
||||
$(this).toggleClass('disabled', $q.val() <= ($q.data('min')||0));
|
||||
});
|
||||
$el.find('a[data-increase_tolerance]').each(function() {
|
||||
var $t = $el.find('#t_'+$(this).data('increase_tolerance'));
|
||||
$(this).toggleClass('disabled', $t.val() >= $t.data('max'));
|
||||
});
|
||||
$el.find('a[data-decrease_tolerance]').each(function() {
|
||||
var $t = $el.find('#t_'+$(this).data('decrease_tolerance'));
|
||||
$(this).toggleClass('disabled', $t.val() <= ($t.data('min')||0));
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$('input[data-increase_quantity]').on('touchclick', function() {
|
||||
$('a[data-increase_quantity]').on('touchclick', function() {
|
||||
increaseQuantity($(this).data('increase_quantity'));
|
||||
});
|
||||
$('input[data-decrease_quantity]').on('touchclick', function() {
|
||||
$('a[data-decrease_quantity]').on('touchclick', function() {
|
||||
decreaseQuantity($(this).data('decrease_quantity'));
|
||||
});
|
||||
$('input[data-increase_tolerance]').on('touchclick', function() {
|
||||
$('a[data-increase_tolerance]').on('touchclick', function() {
|
||||
increaseTolerance($(this).data('increase_tolerance'));
|
||||
});
|
||||
$('input[data-decrease_tolerance]').on('touchclick', function() {
|
||||
$('a[data-decrease_tolerance]').on('touchclick', function() {
|
||||
decreaseTolerance($(this).data('decrease_tolerance'));
|
||||
});
|
||||
|
||||
$('a[data-confirm_switch_order]').on('touchclick', function() {
|
||||
return (!modified || confirm(I18n.t('js.ordering.confirm_change')));
|
||||
});
|
||||
|
||||
updateButtons($(document));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -197,10 +197,17 @@ table {
|
|||
}
|
||||
.unused {
|
||||
color: @articleUnusedColor;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
.partused {
|
||||
color: @articlePartusedColor;
|
||||
}
|
||||
.btn-ordering, .btn-group .btn-ordering {
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
padding: 4px 8px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
#order-footer, .article-info {
|
||||
text-align: left;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class Admin::ConfigsController < Admin::BaseController
|
|||
# turn recurring rules into something palatable
|
||||
def parse_recurring_selects!(config)
|
||||
if config
|
||||
for k in [:pickup, :ends] do
|
||||
for k in [:pickup, :boxfill, :ends] do
|
||||
if config[k]
|
||||
# allow clearing it using dummy value '{}' ('' would break recurring_select)
|
||||
if config[k][:recurr].present? && config[k][:recurr] != '{}'
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ module Admin::ConfigsHelper
|
|||
checked_value = options.delete(:checked_value) || 'true'
|
||||
unchecked_value = options.delete(:unchecked_value) || 'false'
|
||||
options[:checked] = 'checked' if v=options.delete(:value) && v!='false'
|
||||
form.hidden_field(key, value: unchecked_value, as: :hidden) + form.check_box(key, options, checked_value, false)
|
||||
# different key for hidden field so that allow clocking on label focuses the control
|
||||
form.hidden_field(key, id: "#{key}_", value: unchecked_value, as: :hidden) + form.check_box(key, options, checked_value, false)
|
||||
elsif options[:as] == :select_recurring
|
||||
options[:value] = FoodsoftDateUtil.rule_from(options[:value])
|
||||
options[:rules] ||= []
|
||||
|
|
@ -111,6 +112,13 @@ module Admin::ConfigsHelper
|
|||
end
|
||||
end
|
||||
|
||||
# @return [String] Tooltip element (span)
|
||||
# @param form [ActionView::Helpers::FormBuilder] Form object.
|
||||
# @param key [Symbol, String] Configuration key of a boolean (e.g. +use_messages+).
|
||||
def config_tooltip(form, key, options={}, &block)
|
||||
content_tag :span, config_input_tooltip_options(form, key, options), &block
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def config_input_tooltip_options(form, key, options)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class GroupOrder < ActiveRecord::Base
|
|||
data[:order_articles] = {}
|
||||
order.articles_grouped_by_category.each do |article_category, order_articles|
|
||||
order_articles.each do |order_article|
|
||||
|
||||
|
||||
# Get the result of last time ordering, if possible
|
||||
goa = group_order_articles.detect { |goa| goa.order_article_id == order_article.id }
|
||||
|
||||
|
|
@ -58,8 +58,10 @@ class GroupOrder < ActiveRecord::Base
|
|||
group_order_article = group_order_articles.where(order_article_id: order_article.id).first_or_create
|
||||
|
||||
# Get ordered quantities and update group_order_articles/_quantities...
|
||||
quantities = group_order_articles_attributes.fetch(order_article.id.to_s, {:quantity => 0, :tolerance => 0})
|
||||
group_order_article.update_quantities(quantities[:quantity].to_i, quantities[:tolerance].to_i)
|
||||
if group_order_articles_attributes
|
||||
quantities = group_order_articles_attributes.fetch(order_article.id.to_s, {:quantity => 0, :tolerance => 0})
|
||||
group_order_article.update_quantities(quantities[:quantity].to_i, quantities[:tolerance].to_i)
|
||||
end
|
||||
|
||||
# Also update results for the order_article
|
||||
logger.debug "[save_group_order_articles] update order_article.results!"
|
||||
|
|
@ -86,4 +88,3 @@ class GroupOrder < ActiveRecord::Base
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
group_order.try!(:ordergroup_id)
|
||||
end
|
||||
|
||||
# Updates the quantity/tolerance for this GroupOrderArticle by updating both GroupOrderArticle properties
|
||||
# Updates the quantity/tolerance for this GroupOrderArticle by updating both GroupOrderArticle properties
|
||||
# and the associated GroupOrderArticleQuantities chronologically.
|
||||
#
|
||||
#
|
||||
# See description of the ordering algorithm in the general application documentation for details.
|
||||
def update_quantities(quantity, tolerance)
|
||||
logger.debug("GroupOrderArticle[#{id}].update_quantities(#{quantity}, #{tolerance})")
|
||||
|
|
@ -104,7 +104,7 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
|
||||
# Determines how many items of this article the Ordergroup receives.
|
||||
# Returns a hash with three keys: :quantity / :tolerance / :total
|
||||
#
|
||||
#
|
||||
# See description of the ordering algorithm in the general application documentation for details.
|
||||
def calculate_result(total = nil)
|
||||
# return memoized result unless a total is given
|
||||
|
|
@ -199,5 +199,3 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
result != result_computed unless result.nil?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class Order < ActiveRecord::Base
|
|||
# Allow separate inputs for date and time
|
||||
# with workaround for https://github.com/einzige/date_time_attribute/issues/14
|
||||
include DateTimeAttributeValidate
|
||||
date_time_attribute :starts, :ends
|
||||
date_time_attribute :starts, :boxfill, :ends
|
||||
|
||||
def stockit?
|
||||
supplier_id == 0
|
||||
|
|
@ -92,8 +92,16 @@ class Order < ActiveRecord::Base
|
|||
state == "closed"
|
||||
end
|
||||
|
||||
def boxfill?
|
||||
FoodsoftConfig[:use_boxfill] && open? && boxfill.present? && boxfill < Time.now
|
||||
end
|
||||
|
||||
def is_boxfill_useful?
|
||||
FoodsoftConfig[:use_boxfill] && supplier.try(:has_tolerance?)
|
||||
end
|
||||
|
||||
def expired?
|
||||
!ends.nil? && ends < Time.now
|
||||
ends.present? && ends < Time.now
|
||||
end
|
||||
|
||||
# sets up first guess of dates when initializing a new object
|
||||
|
|
@ -105,7 +113,8 @@ class Order < ActiveRecord::Base
|
|||
last = (DateTime.parse(FoodsoftConfig[:order_schedule][:initial]) rescue nil)
|
||||
last ||= Order.finished.reorder(:starts).first.try(:starts)
|
||||
last ||= self.starts
|
||||
# adjust end date
|
||||
# adjust boxfill and end date
|
||||
self.boxfill ||= FoodsoftDateUtil.next_occurrence last, self.starts, FoodsoftConfig[:order_schedule][:boxfill] if is_boxfill_useful?
|
||||
self.ends ||= FoodsoftDateUtil.next_occurrence last, self.starts, FoodsoftConfig[:order_schedule][:ends]
|
||||
end
|
||||
self
|
||||
|
|
@ -251,7 +260,9 @@ class Order < ActiveRecord::Base
|
|||
|
||||
def starts_before_ends
|
||||
delta = Rails.env.test? ? 1 : 0 # since Rails 4.2 tests appear to have time differences, with this validation failing
|
||||
errors.add(:ends, I18n.t('orders.model.error_starts_before_ends')) if (ends && starts && ends <= (starts-delta))
|
||||
errors.add(:ends, I18n.t('orders.model.error_starts_before_ends')) if ends && starts && ends <= (starts-delta)
|
||||
errors.add(:ends, I18n.t('orders.model.error_boxfill_before_ends')) if ends && boxfill && ends <= (boxfill-delta)
|
||||
errors.add(:boxfill, I18n.t('orders.model.error_starts_before_boxfill')) if boxfill && starts && boxfill <= (starts-delta)
|
||||
end
|
||||
|
||||
def include_articles
|
||||
|
|
@ -288,4 +299,3 @@ class Order < ActiveRecord::Base
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class OrderArticle < ActiveRecord::Base
|
|||
units_to_order
|
||||
end
|
||||
|
||||
# Count quantities of belonging group_orders.
|
||||
# Count quantities of belonging group_orders.
|
||||
# In balancing this can differ from ordered (by supplier) quantity for this article.
|
||||
def group_orders_sum
|
||||
quantity = group_order_articles.collect(&:result).sum
|
||||
|
|
@ -42,10 +42,11 @@ class OrderArticle < ActiveRecord::Base
|
|||
# Update quantity/tolerance/units_to_order from group_order_articles
|
||||
def update_results!
|
||||
if order.open?
|
||||
quantity = group_order_articles.collect(&:quantity).sum
|
||||
tolerance = group_order_articles.collect(&:tolerance).sum
|
||||
update_attributes(:quantity => quantity, :tolerance => tolerance,
|
||||
:units_to_order => calculate_units_to_order(quantity, tolerance))
|
||||
self.quantity = group_order_articles.collect(&:quantity).sum
|
||||
self.tolerance = group_order_articles.collect(&:tolerance).sum
|
||||
self.units_to_order = calculate_units_to_order(quantity, tolerance)
|
||||
enforce_boxfill if order.boxfill?
|
||||
save!
|
||||
elsif order.finished?
|
||||
update_attribute(:units_to_order, group_order_articles.collect(&:result).sum)
|
||||
end
|
||||
|
|
@ -186,19 +187,20 @@ class OrderArticle < ActiveRecord::Base
|
|||
|
||||
# @return [Number] Units missing for the last +unit_quantity+ of the article.
|
||||
def missing_units
|
||||
units = price.unit_quantity - ((quantity % price.unit_quantity) + tolerance)
|
||||
units = 0 if units < 0
|
||||
units = 0 if units == price.unit_quantity
|
||||
units
|
||||
_missing_units(price.unit_quantity, quantity, tolerance)
|
||||
end
|
||||
|
||||
|
||||
def missing_units_was
|
||||
_missing_units(price.unit_quantity, quantity_was, tolerance_was)
|
||||
end
|
||||
|
||||
# Check if the result of any associated GroupOrderArticle was overridden manually
|
||||
def result_manually_changed?
|
||||
group_order_articles.any? {|goa| goa.result_manually_changed?}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
def article_and_price_exist
|
||||
errors.add(:article, I18n.t('model.order_article.error_price')) if !(article = Article.find(article_id)) || article.fc_price.nil?
|
||||
rescue
|
||||
|
|
@ -219,5 +221,26 @@ class OrderArticle < ActiveRecord::Base
|
|||
order.group_orders.each(&:update_price!)
|
||||
end
|
||||
|
||||
end
|
||||
# Throws an exception when the changed article decreases the amount of filled boxes.
|
||||
def enforce_boxfill
|
||||
# Either nothing changes, or the tolerance increases,
|
||||
# missing_units decreases and the amount doesn't decrease, or
|
||||
# tolerance was moved to quantity. Only then are changes allowed in the boxfill phase.
|
||||
delta_q = quantity - quantity_was
|
||||
delta_t = tolerance - tolerance_was
|
||||
delta_mis = missing_units - missing_units_was
|
||||
delta_box = units_to_order - units_to_order_was
|
||||
unless (delta_q == 0 && delta_t >= 0) ||
|
||||
(delta_mis < 0 && delta_box >= 0 && delta_t >= 0) ||
|
||||
(delta_q > 0 && delta_q == -delta_t)
|
||||
raise ActiveRecord::RecordNotSaved.new("Change not acceptable in boxfill phase for '#{article.name}', sorry.", self)
|
||||
end
|
||||
end
|
||||
|
||||
def _missing_units(unit_quantity, quantity, tolerance)
|
||||
units = unit_quantity - ((quantity % unit_quantity) + tolerance)
|
||||
units = 0 if units < 0
|
||||
units = 0 if units == unit_quantity
|
||||
units
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -116,6 +116,11 @@ class Supplier < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
# @return [Boolean] Whether there are articles that would use tolerance (unit_quantity > 1)
|
||||
def has_tolerance?
|
||||
articles.where('articles.unit_quantity > 1').any?
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# make sure the shared_sync_method is allowed for the shared supplier
|
||||
|
|
|
|||
|
|
@ -11,8 +11,18 @@
|
|||
%span.add-on= t 'number.currency.format.unit'
|
||||
= config_input_field form, :minimum_balance, as: :decimal, class: 'input-small'
|
||||
|
||||
%h4= t '.schedule_title'
|
||||
= form.simple_fields_for :order_schedule do |fields|
|
||||
#boxfill-schedule.collapse{class: ('in' if FoodsoftConfig[:use_boxfill])}
|
||||
= fields.simple_fields_for 'boxfill' do |fields|
|
||||
.fold-line
|
||||
= config_input fields, 'recurr', as: :select_recurring, input_html: {class: 'input-xlarge'}
|
||||
= config_input fields, 'time', input_html: {class: 'input-mini'}
|
||||
= fields.simple_fields_for 'ends' do |fields|
|
||||
.fold-line
|
||||
= config_input fields, 'recurr', as: :select_recurring, input_html: {class: 'input-xlarge'}, allow_blank: true
|
||||
= config_input fields, 'time', input_html: {class: 'input-mini'}
|
||||
-# can't use collapse and tooltip on same element :/
|
||||
= config_input form, :use_boxfill, as: :boolean do
|
||||
= config_tooltip form, :use_boxfill do
|
||||
= config_input_field form, :use_boxfill, as: :boolean, title: '', data: {toggle: 'collapse', target: '#boxfill-schedule'}
|
||||
|
|
|
|||
|
|
@ -102,21 +102,27 @@
|
|||
%span{id: "missing_units_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:missing_units]
|
||||
|
||||
%td.quantity
|
||||
%input{id: "q_#{order_article.id}", name: "group_order[group_order_articles_attributes][#{order_article.id}][quantity]", size: "2", type: "hidden", value: @ordering_data[:order_articles][order_article.id][:quantity]}/
|
||||
%input{id: "q_#{order_article.id}", name: "group_order[group_order_articles_attributes][#{order_article.id}][quantity]", type: "hidden", value: @ordering_data[:order_articles][order_article.id][:quantity], 'data-min' => (@ordering_data[:order_articles][order_article.id][:quantity] if @order.boxfill?), 'data-max' => (@ordering_data[:order_articles][order_article.id][:quantity]+@ordering_data[:order_articles][order_article.id][:missing_units] if @order.boxfill?)}/
|
||||
%span.used{id: "q_used_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:used_quantity]
|
||||
+
|
||||
%span.unused{id: "q_unused_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:quantity] - @ordering_data[:order_articles][order_article.id][:used_quantity]
|
||||
%input{type: 'button', value: '+', 'data-increase_quantity' => order_article.id}
|
||||
%input{type: 'button', value: '-', 'data-decrease_quantity' => order_article.id}
|
||||
.btn-group
|
||||
%a.btn.btn-ordering{'data-increase_quantity' => order_article.id}
|
||||
%i.icon-plus
|
||||
%a.btn.btn-ordering{'data-decrease_quantity' => order_article.id}
|
||||
%i.icon-minus
|
||||
|
||||
%td.tolerance{style: ('display:none' if @order.stockit?)}
|
||||
%input{id: "t_#{order_article.id}", name: "group_order[group_order_articles_attributes][#{order_article.id}][tolerance]", size: "2", type: "hidden", value: @ordering_data[:order_articles][order_article.id][:tolerance]}/
|
||||
%input{id: "t_#{order_article.id}", name: "group_order[group_order_articles_attributes][#{order_article.id}][tolerance]", type: "hidden", value: @ordering_data[:order_articles][order_article.id][:tolerance], 'data-min' => (@ordering_data[:order_articles][order_article.id][:tolerance] if @order.boxfill?)}/
|
||||
- if (@ordering_data[:order_articles][order_article.id][:unit] > 1)
|
||||
%span.used{id: "t_used_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:used_tolerance]
|
||||
+
|
||||
%span.unused{id: "t_unused_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:tolerance] - @ordering_data[:order_articles][order_article.id][:used_tolerance]
|
||||
%input{type: 'button', value: '+', 'data-increase_tolerance' => order_article.id}
|
||||
%input{type: 'button', value: '-', 'data-decrease_tolerance' => order_article.id}
|
||||
.btn-group
|
||||
%a.btn.btn-ordering{'data-increase_tolerance' => order_article.id}
|
||||
%i.icon-plus
|
||||
%a.btn.btn-ordering{'data-decrease_tolerance' => order_article.id}
|
||||
%i.icon-minus
|
||||
|
||||
%td{id: "td_price_#{order_article.id}", style: "text-align:right; padding-right:10px; width:4em"}
|
||||
%span{id: "price_#{order_article.id}_display"}= number_to_currency(@ordering_data[:order_articles][order_article.id][:total_price])
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
= f.hidden_field :supplier_id
|
||||
.fold-line
|
||||
= f.input :starts, as: :date_picker_time
|
||||
= f.input :boxfill, as: :date_picker_time if @order.is_boxfill_useful?
|
||||
= f.input :ends, as: :date_picker_time
|
||||
= f.input :note, input_html: {rows: 2, class: 'input-xxlarge'}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue