Merge branch 'master' into updated-gems
This commit is contained in:
commit
9fb6597980
38 changed files with 352 additions and 223 deletions
|
|
@ -10,6 +10,7 @@ var groupBalance = 0; // available group money
|
|||
var currencySeparator = "."; // default decimal separator
|
||||
var currencyPrecision = 2; // default digits behind comma
|
||||
var currencyUnit = "€"; // default currency
|
||||
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
|
||||
|
||||
|
|
@ -40,6 +41,10 @@ function setGroupBalance(amount) {
|
|||
groupBalance = amount;
|
||||
}
|
||||
|
||||
function setMinimumBalance(amount) {
|
||||
minimumBalance = amount;
|
||||
}
|
||||
|
||||
function addData(orderArticleId, itemPrice, itemUnit, itemSubtotal, itemQuantityOthers, itemToleranceOthers, allocated, available) {
|
||||
var i = orderArticleId;
|
||||
price[i] = itemPrice;
|
||||
|
|
@ -159,7 +164,7 @@ function updateBalance() {
|
|||
$('#total_balance').val(asMoney(balance));
|
||||
// determine bgcolor and submit button state according to balance
|
||||
var bgcolor = '';
|
||||
if (balance < 0) {
|
||||
if (balance < minimumBalance) {
|
||||
bgcolor = '#FF0000';
|
||||
$('#submit_button').attr('disabled', 'disabled')
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -55,4 +55,9 @@ class StockitController < ApplicationController
|
|||
|
||||
render :partial => 'form', :locals => {:stock_article => stock_article}
|
||||
end
|
||||
|
||||
def history
|
||||
@stock_article = StockArticle.undeleted.find(params[:stock_article_id])
|
||||
@stock_changes = @stock_article.stock_changes.order('stock_changes.created_at DESC').each {|s| s.readonly!}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ class TasksController < ApplicationController
|
|||
|
||||
def create
|
||||
@task = Task.new(params[:task])
|
||||
if params[:periodic]
|
||||
@task.periodic_task_group = PeriodicTaskGroup.new
|
||||
end
|
||||
if @task.save
|
||||
redirect_to tasks_url, :notice => I18n.t('tasks.create.notice')
|
||||
else
|
||||
|
|
@ -32,13 +35,20 @@ class TasksController < ApplicationController
|
|||
def edit
|
||||
@task = Task.find(params[:id])
|
||||
@task.current_user_id = current_user.id
|
||||
if @task.periodic?
|
||||
flash.now[:alert] = I18n.t('tasks.edit.warning_periodic').html_safe
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@task = Task.find(params[:id])
|
||||
was_periodic = @task.periodic?
|
||||
@task.attributes=(params[:task])
|
||||
if @task.errors.empty? && @task.save
|
||||
flash[:notice] = I18n.t('tasks.update.notice')
|
||||
if was_periodic and not @task.periodic?
|
||||
flash[:notice] = I18n.t('tasks.update.notice_converted')
|
||||
end
|
||||
if @task.workgroup
|
||||
redirect_to workgroup_tasks_url(workgroup_id: @task.workgroup_id)
|
||||
else
|
||||
|
|
@ -53,7 +63,12 @@ class TasksController < ApplicationController
|
|||
task = Task.find(params[:id])
|
||||
# Save user_ids to update apple statistics after destroy
|
||||
user_ids = task.user_ids
|
||||
task.destroy
|
||||
if params[:periodic]
|
||||
task.periodic_task_group.exclude_tasks_before(task)
|
||||
task.periodic_task_group.destroy
|
||||
else
|
||||
task.destroy
|
||||
end
|
||||
task.update_ordergroup_stats(user_ids)
|
||||
|
||||
redirect_to tasks_url, :notice => I18n.t('tasks.destroy.notice')
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module Finance::OrderArticlesHelper
|
|||
if @order.stockit?
|
||||
StockArticle.order('articles.name')
|
||||
else
|
||||
@order.supplier.articles.order('articles.name')
|
||||
@order.supplier.articles.undeleted.order('articles.name')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,4 +4,14 @@ module StockitHelper
|
|||
class_names << "unavailable" if article.quantity_available <= 0
|
||||
class_names.join(" ")
|
||||
end
|
||||
|
||||
def link_to_stock_change_reason(stock_change)
|
||||
if stock_change.delivery_id
|
||||
link_to t('.delivery'), supplier_delivery_path(stock_change.delivery.supplier, stock_change.delivery)
|
||||
elsif stock_change.order_id
|
||||
link_to t('.order'), order_path(stock_change.order)
|
||||
elsif stock_change.stock_taking_id
|
||||
link_to t('.stock_taking'), stock_taking_path(stock_change.stock_taking)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -108,13 +108,13 @@ class Ordergroup < Group
|
|||
|
||||
# Make sure, the name is uniq, add usefull message if uniq group is already deleted
|
||||
def uniqueness_of_name
|
||||
id = new_record? ? nil : self.id
|
||||
group = Ordergroup.where('groups.id != ? AND groups.name = ?', id, name).first
|
||||
if group.present?
|
||||
message = group.deleted? ? :taken_with_deleted : :taken
|
||||
group = Ordergroup.where('groups.name = ?', name)
|
||||
group = group.where('groups.id != ?', self.id) unless new_record?
|
||||
if group.exists?
|
||||
message = group.first.deleted? ? :taken_with_deleted : :taken
|
||||
errors.add :name, message
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
29
app/models/periodic_task_group.rb
Normal file
29
app/models/periodic_task_group.rb
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
class PeriodicTaskGroup < ActiveRecord::Base
|
||||
has_many :tasks, dependent: :destroy
|
||||
|
||||
PeriodDays = 7
|
||||
|
||||
def has_next_task?
|
||||
return false if tasks.empty?
|
||||
return false if tasks.first.due_date.nil?
|
||||
return true
|
||||
end
|
||||
|
||||
def create_next_task
|
||||
template_task = tasks.first
|
||||
self.next_task_date ||= template_task.due_date + PeriodDays
|
||||
|
||||
next_task = template_task.dup
|
||||
next_task.due_date = next_task_date
|
||||
next_task.save
|
||||
|
||||
self.next_task_date += PeriodDays
|
||||
self.save
|
||||
end
|
||||
|
||||
def exclude_tasks_before(task)
|
||||
tasks.where("due_date < '#{task.due_date}'").each do |t|
|
||||
t.update_attribute(:periodic_task_group, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -17,6 +17,10 @@ class StockArticle < Article
|
|||
quantity - OrderArticle.where(article_id: id).
|
||||
joins(:order).where("orders.state = 'open' OR orders.state = 'finished'").sum(:units_to_order)
|
||||
end
|
||||
|
||||
def quantity_history
|
||||
stock_changes.reorder('stock_changes.created_at ASC').map{|s| s.quantity}.cumulative_sum
|
||||
end
|
||||
|
||||
def self.stock_value
|
||||
available.collect { |a| a.quantity * a.gross_price }.sum
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
class StockChange < ActiveRecord::Base
|
||||
belongs_to :delivery
|
||||
belongs_to :order
|
||||
belongs_to :stock_taking
|
||||
belongs_to :stock_article
|
||||
|
||||
validates_presence_of :stock_article_id, :quantity
|
||||
|
|
|
|||
|
|
@ -82,10 +82,10 @@ class Supplier < ActiveRecord::Base
|
|||
|
||||
# Make sure, the name is uniq, add usefull message if uniq group is already deleted
|
||||
def uniqueness_of_name
|
||||
id = new_record? ? nil : self.id
|
||||
supplier = Supplier.where('suppliers.id != ? AND suppliers.name = ?', id, name).first
|
||||
if supplier.present?
|
||||
message = supplier.deleted? ? :taken_with_deleted : :taken
|
||||
supplier = Supplier.where('suppliers.name = ?', name)
|
||||
supplier = supplier.where('suppliers.id != ?', self.id) unless new_record?
|
||||
if supplier.exists?
|
||||
message = supplier.first.deleted? ? :taken_with_deleted : :taken
|
||||
errors.add :name, message
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
class Task < ActiveRecord::Base
|
||||
has_many :assignments, :dependent => :destroy
|
||||
has_many :users, :through => :assignments
|
||||
belongs_to :workgroup
|
||||
belongs_to :periodic_task_group
|
||||
|
||||
scope :non_group, where(workgroup_id: nil, done: false)
|
||||
scope :done, where(done: true)
|
||||
|
|
@ -16,7 +18,9 @@ class Task < ActiveRecord::Base
|
|||
validates :required_users, :presence => true
|
||||
validates_numericality_of :duration, :required_users, :only_integer => true, :greater_than => 0
|
||||
validates_length_of :description, maximum: 250
|
||||
validates :done, exclusion: { in: [true] }, if: :periodic?, on: :create
|
||||
|
||||
before_save :exclude_from_periodic_task_group, if: :changed?, unless: :new_record?
|
||||
after_save :update_ordergroup_stats
|
||||
|
||||
# Find all tasks, for which the current user should be responsible
|
||||
|
|
@ -46,6 +50,10 @@ class Task < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def periodic?
|
||||
not periodic_task_group.nil?
|
||||
end
|
||||
|
||||
def is_assigned?(user)
|
||||
self.assignments.detect {|ass| ass.user_id == user.id }
|
||||
end
|
||||
|
|
@ -100,5 +108,10 @@ class Task < ActiveRecord::Base
|
|||
def update_ordergroup_stats(user_ids = self.user_ids)
|
||||
Ordergroup.joins(:users).where(users: {id: user_ids}).each(&:update_stats!)
|
||||
end
|
||||
|
||||
def exclude_from_periodic_task_group
|
||||
self.periodic_task_group = nil
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,51 +6,9 @@ class Workgroup < Group
|
|||
has_many :open_tasks, :class_name => 'Task', :conditions => ['done = ?', false], :order => 'due_date ASC'
|
||||
|
||||
validates_uniqueness_of :name
|
||||
validates_presence_of :task_name, :weekday, :task_required_users, :next_weekly_tasks_number,
|
||||
:if => :weekly_task
|
||||
validates_numericality_of :next_weekly_tasks_number, :greater_than => 0, :less_than => 21, :only_integer => true,
|
||||
:if => :weekly_task
|
||||
validates_length_of :task_description, maximum: 250
|
||||
validate :last_admin_on_earth, :on => :update
|
||||
before_destroy :check_last_admin_group
|
||||
|
||||
def self.weekdays
|
||||
days = I18n.t('date.day_names')
|
||||
(0..days.length-1).map {|i| [days[i], i.to_s]}
|
||||
end
|
||||
|
||||
# Returns an Array with date-objects to represent the next weekly-tasks
|
||||
def next_weekly_tasks
|
||||
# our system starts from 0 (sunday) to 6 (saturday)
|
||||
# get difference between groups weekday and now
|
||||
diff = self.weekday - Time.now.wday
|
||||
if diff >= 0
|
||||
# weektask is in current week
|
||||
nextTask = diff.day.from_now
|
||||
else
|
||||
# weektask is in the next week
|
||||
nextTask = (diff + 7).day.from_now
|
||||
end
|
||||
# now generate the Array
|
||||
nextTasks = Array.new
|
||||
next_weekly_tasks_number.times do
|
||||
nextTasks << nextTask.to_date
|
||||
nextTask = 1.week.from_now(nextTask)
|
||||
end
|
||||
return nextTasks
|
||||
end
|
||||
|
||||
def task_attributes(date)
|
||||
{
|
||||
:name => task_name,
|
||||
:description => task_description,
|
||||
:due_date => date,
|
||||
:required_users => task_required_users,
|
||||
:duration => task_duration,
|
||||
:weekly => true
|
||||
}
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Check before destroy a group, if this is the last group with admin role
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#{data_to_js(@ordering_data)}
|
||||
setGroupBalance(#{@ordering_data[:available_funds]});
|
||||
setCurrencyFormat("#{t('number.currency.format.separator')}", #{t('number.currency.format.precision')}, "#{t('number.currency.format.unit')}");
|
||||
setMinimumBalance(#{FoodsoftConfig[:minimum_balance] or 0});
|
||||
setToleranceBehaviour(#{FoodsoftConfig[:tolerance_is_costly]});
|
||||
setStockit(#{@order.stockit?});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -45,26 +45,6 @@
|
|||
= f.label :role_orders
|
||||
%br/
|
||||
= f.check_box :role_orders
|
||||
%p
|
||||
= f.label :weekly_task
|
||||
%br/
|
||||
= f.check_box :weekly_task
|
||||
%p
|
||||
= f.label :weekday
|
||||
%br/
|
||||
= f.text_field :weekday
|
||||
%p
|
||||
= f.label :task_name
|
||||
%br/
|
||||
= f.text_field :task_name
|
||||
%p
|
||||
= f.label :task_description
|
||||
%br/
|
||||
= f.text_field :task_description
|
||||
%p
|
||||
= f.label :task_required_users
|
||||
%br/
|
||||
= f.text_field :task_required_users
|
||||
%p
|
||||
= f.label :deleted_at
|
||||
%br/
|
||||
|
|
|
|||
|
|
@ -12,11 +12,6 @@
|
|||
%th Role Article Meta
|
||||
%th Role Finance
|
||||
%th Role Orders
|
||||
%th Weekly Task
|
||||
%th Weekday
|
||||
%th Task Name
|
||||
%th Task Description
|
||||
%th Task Required Users
|
||||
%th Deleted At
|
||||
%th Contact Person
|
||||
%th Contact Phone
|
||||
|
|
@ -34,11 +29,6 @@
|
|||
%td= h ordergroup.role_article_meta
|
||||
%td= h ordergroup.role_finance
|
||||
%td= h ordergroup.role_orders
|
||||
%td= h ordergroup.weekly_task
|
||||
%td= h ordergroup.weekday
|
||||
%td= h ordergroup.task_name
|
||||
%td= h ordergroup.task_description
|
||||
%td= h ordergroup.task_required_users
|
||||
%td= h ordergroup.deleted_at
|
||||
%td= h ordergroup.contact_person
|
||||
%td= h ordergroup.contact_phone
|
||||
|
|
|
|||
|
|
@ -29,7 +29,10 @@
|
|||
- if order.stockit?
|
||||
%td= units
|
||||
- else
|
||||
%td= "#{order_article.quantity} + #{order_article.tolerance}" if unit_quantity > 1
|
||||
- if unit_quantity > 1 or order_article.tolerance > 0
|
||||
%td= "#{order_article.quantity} + #{order_article.tolerance}"
|
||||
- else
|
||||
%td= "#{order_article.quantity}"
|
||||
%td= units
|
||||
%p
|
||||
= t '.prices_sum'
|
||||
|
|
|
|||
|
|
@ -13,13 +13,6 @@
|
|||
- members = group.users
|
||||
= "(#{members.size})"
|
||||
= members.collect(&:nick).join(", ")
|
||||
- if group.is_a?(Workgroup)
|
||||
%dt= t('.weekly_job') + ':'
|
||||
%dd
|
||||
- if group.weekly_task
|
||||
=h "#{group.task_name} am #{weekday(group.weekday)}"
|
||||
- else
|
||||
= t '.no_weekly_job'
|
||||
- else
|
||||
- unless group.is_a?(Workgroup)
|
||||
%dt= t '.apple_limit'
|
||||
%dd= group.ignore_apple_restriction ? t('.deactivated') : t('.activated')
|
||||
|
|
|
|||
|
|
@ -3,17 +3,6 @@
|
|||
|
||||
= yield
|
||||
|
||||
- if f.object.is_a?(Workgroup)
|
||||
%h3= t '.title'
|
||||
= f.input :weekly_task
|
||||
#weekly_task_fields
|
||||
= f.input :weekday, as: :select, collection: Workgroup.weekdays
|
||||
= f.input :task_name
|
||||
= f.input :task_required_users
|
||||
= f.input :task_duration, :as => :select, :collection => (1..3)
|
||||
= f.input :task_description, as: :text, input_html: {rows: 5}
|
||||
= f.input :next_weekly_tasks_number
|
||||
|
||||
= f.input :user_tokens, :as => :string,
|
||||
:input_html => { 'data-pre' => f.object.users.map { |u| u.token_attributes }.to_json }
|
||||
|
||||
|
|
|
|||
17
app/views/stockit/history.haml
Normal file
17
app/views/stockit/history.haml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
- title t('.stock_changes', :article_name => @stock_article.name)
|
||||
|
||||
%table.table.table-hover#stock_changes
|
||||
%thead
|
||||
%tr
|
||||
%th= t '.datetime'
|
||||
%th= t '.reason'
|
||||
%th= t '.change_quantity'
|
||||
%th= t '.new_quantity'
|
||||
%tbody
|
||||
- reversed_history = @stock_article.quantity_history.reverse
|
||||
- @stock_changes.each_with_index do |stock_change, index|
|
||||
%tr
|
||||
%td= l stock_change.created_at
|
||||
%td= link_to_stock_change_reason(stock_change)
|
||||
%td= stock_change.quantity
|
||||
%td= reversed_history[index]
|
||||
|
|
@ -56,6 +56,7 @@
|
|||
%td= article.article_category.name
|
||||
%td
|
||||
= link_to t('ui.edit'), edit_stock_article_path(article), class: 'btn btn-mini'
|
||||
= link_to t('ui.history'), stock_article_history_path(article), class: 'btn btn-mini'
|
||||
= link_to t('ui.delete'), article, :method => :delete, :confirm => t('.confirm_delete'),
|
||||
class: 'btn btn-mini btn-danger', :remote => true
|
||||
%p
|
||||
|
|
|
|||
|
|
@ -25,5 +25,7 @@
|
|||
= f.input :due_date, as: :date_picker
|
||||
= f.input :done
|
||||
.form-actions
|
||||
= f.submit class: 'btn'
|
||||
= f.submit class: 'btn btn-primary'
|
||||
- if @task.new_record?
|
||||
= f.submit t('.submit.periodic'), name: 'periodic', class: 'btn'
|
||||
= link_to t('ui.or_cancel'), :back
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
%thead
|
||||
%tr
|
||||
%th= t '.due_date'
|
||||
%th
|
||||
%th= t '.task'
|
||||
%th{:colspan => '2'}
|
||||
= t '.who'
|
||||
|
|
@ -11,6 +12,9 @@
|
|||
- done = task.done ? " done" : ""
|
||||
%tr{:class => done }
|
||||
%td= format_date(task.due_date) unless task.due_date.nil?
|
||||
%td
|
||||
- if task.periodic?
|
||||
%i.icon-repeat{title: t('tasks.repeated')}
|
||||
%td= link_to t('.task_format', name: task.name, duration: task.duration), task_path(task)
|
||||
%td
|
||||
= task_assignments task
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@
|
|||
%dd= simple_format(@task.description)
|
||||
- if @task.due_date.present?
|
||||
%dt= t '.due_date'
|
||||
%dd= format_date(@task.due_date)
|
||||
%dd
|
||||
= format_date(@task.due_date)
|
||||
- if @task.periodic?
|
||||
%i.icon-repeat{title: t('tasks.repeated')}
|
||||
%dt= t 'simple_form.labels.task.duration'
|
||||
%dd= t('.hours', count: @task.duration)
|
||||
%dt= t 'simple_form.labels.task.user_list'
|
||||
|
|
@ -29,3 +32,6 @@
|
|||
= link_to t('ui.edit'), edit_task_path(@task), class: 'btn'
|
||||
= link_to t('ui.delete'), task_path(@task), :method => :delete, :confirm => "Die Aufgabe wirklich löschen?",
|
||||
class: 'btn btn-danger'
|
||||
- if @task.periodic?
|
||||
= link_to t('.delete_group'), task_path(@task, periodic: true), method: :delete,
|
||||
confirm: t('.confirm_delete_group'), class: 'btn btn-danger'
|
||||
|
|
|
|||
|
|
@ -1,16 +1,6 @@
|
|||
- title t('.title', workgroup: @group.name)
|
||||
= render 'nav'
|
||||
|
||||
%section.well
|
||||
%h3= t '.weekly.title'
|
||||
- if @group.weekly_task
|
||||
= t('.weekly.desc', weekday: weekday(@group.weekday), task: @group.task_name).html_safe
|
||||
- else
|
||||
= t('.weekly.empty').html_safe
|
||||
|
||||
- if @current_user.member_of?(@group) or @current_user.role_admin?
|
||||
= link_to t('.weekly.edit'), edit_foodcoop_workgroup_path(@group), class: 'btn'
|
||||
|
||||
%section
|
||||
%h3= t '.title_all'
|
||||
= render 'list', tasks: @group.open_tasks
|
||||
|
|
|
|||
|
|
@ -45,26 +45,6 @@
|
|||
= f.label :role_orders
|
||||
%br/
|
||||
= f.check_box :role_orders
|
||||
%p
|
||||
= f.label :weekly_task
|
||||
%br/
|
||||
= f.check_box :weekly_task
|
||||
%p
|
||||
= f.label :weekday
|
||||
%br/
|
||||
= f.text_field :weekday
|
||||
%p
|
||||
= f.label :task_name
|
||||
%br/
|
||||
= f.text_field :task_name
|
||||
%p
|
||||
= f.label :task_description
|
||||
%br/
|
||||
= f.text_field :task_description
|
||||
%p
|
||||
= f.label :task_required_users
|
||||
%br/
|
||||
= f.text_field :task_required_users
|
||||
%p
|
||||
= f.label :deleted_at
|
||||
%br/
|
||||
|
|
|
|||
|
|
@ -12,11 +12,6 @@
|
|||
%th Role Article Meta
|
||||
%th Role Finance
|
||||
%th Role Orders
|
||||
%th Weekly Task
|
||||
%th Weekday
|
||||
%th Task Name
|
||||
%th Task Description
|
||||
%th Task Required Users
|
||||
%th Deleted At
|
||||
%th Contact Person
|
||||
%th Contact Phone
|
||||
|
|
@ -34,11 +29,6 @@
|
|||
%td= h workgroup.role_article_meta
|
||||
%td= h workgroup.role_finance
|
||||
%td= h workgroup.role_orders
|
||||
%td= h workgroup.weekly_task
|
||||
%td= h workgroup.weekday
|
||||
%td= h workgroup.task_name
|
||||
%td= h workgroup.task_description
|
||||
%td= h workgroup.task_required_users
|
||||
%td= h workgroup.deleted_at
|
||||
%td= h workgroup.contact_person
|
||||
%td= h workgroup.contact_phone
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue