diff --git a/Gemfile b/Gemfile index 42a9cc09..f311f384 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,6 @@ gem 'haml-rails' gem 'kaminari' gem 'client_side_validations' gem 'simple_form' -gem 'rails3_acts_as_paranoid', "~>0.2.0" gem 'inherited_resources' gem 'localize_input', :git => "git://github.com/bennibu/localize_input.git" gem 'wikicloth' diff --git a/Gemfile.lock b/Gemfile.lock index b44f286d..aabdad24 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -143,8 +143,6 @@ GEM activesupport (= 3.2.11) bundler (~> 1.0) railties (= 3.2.11) - rails3_acts_as_paranoid (0.2.4) - activerecord (~> 3.2) railties (3.2.11) actionpack (= 3.2.11) activesupport (= 3.2.11) @@ -240,7 +238,6 @@ DEPENDENCIES mysql2 prawn rails (~> 3.2.9) - rails3_acts_as_paranoid (~> 0.2.0) resque ruby-prof sass-rails (~> 3.2.3) diff --git a/app/controllers/admin/ordergroups_controller.rb b/app/controllers/admin/ordergroups_controller.rb index 828d91a6..c019ee55 100644 --- a/app/controllers/admin/ordergroups_controller.rb +++ b/app/controllers/admin/ordergroups_controller.rb @@ -3,7 +3,7 @@ class Admin::OrdergroupsController < Admin::BaseController inherit_resources def index - @ordergroups = Ordergroup.order('name ASC') + @ordergroups = Ordergroup.undeleted.order('name ASC') # if somebody uses the search field: unless params[:query].blank? @@ -15,7 +15,7 @@ class Admin::OrdergroupsController < Admin::BaseController def destroy @ordergroup = Ordergroup.find(params[:id]) - @ordergroup.destroy + @ordergroup.mark_as_deleted redirect_to admin_ordergroups_url, :notice => "Bestellgruppe wurde gelöscht" rescue => error redirect_to admin_ordergroups_url, :alert => "Bestellgruppe konnte nicht gelöscht werden: #{error}" diff --git a/app/controllers/articles_controller.rb b/app/controllers/articles_controller.rb index 35bd36db..a9af168e 100644 --- a/app/controllers/articles_controller.rb +++ b/app/controllers/articles_controller.rb @@ -20,7 +20,7 @@ class ArticlesController < ApplicationController sort = "article_categories.name, articles.name" end - @articles = Article.where(supplier_id: @supplier, :type => nil).includes(:article_category).order(sort) + @articles = Article.undeleted.where(supplier_id: @supplier, :type => nil).includes(:article_category).order(sort) @articles = @articles.where('articles.name LIKE ?', "%#{params[:query]}%") unless params[:query].nil? @articles = @articles.page(params[:page]).per(@per_page) @@ -64,13 +64,13 @@ class ArticlesController < ApplicationController # Deletes article from database. send error msg, if article is used in a current order def destroy @article = Article.find(params[:id]) - @article.destroy unless @order = @article.in_open_order # If article is in an active Order, the Order will be returned + @article.mark_as_deleted unless @order = @article.in_open_order # If article is in an active Order, the Order will be returned render :layout => false end # Renders a form for editing all articles from a supplier def edit_all - @articles = @supplier.articles + @articles = @supplier.articles.undeleted end # Updates all article of specific supplier @@ -114,23 +114,24 @@ class ArticlesController < ApplicationController def update_selected raise 'Du hast keine Artikel ausgewählt' if params[:selected_articles].nil? articles = Article.find(params[:selected_articles]) - - case params[:selected_action] - when 'destroy' - articles.each {|a| a.destroy } - flash[:notice] = 'Alle gewählten Artikel wurden gelöscht' - when 'setNotAvailable' - articles.each {|a| a.update_attribute(:availability, false) } - flash[:notice] = 'Alle gewählten Artikel wurden auf "nicht verfügbar" gesetzt' - when 'setAvailable' - articles.each {|a| a.update_attribute(:availability, true) } - flash[:notice] = 'Alle gewählten Artikel wurden auf "verfügbar" gesetzt' - else - flash[:alert] = 'Keine Aktion ausgewählt!' + Article.transaction do + case params[:selected_action] + when 'destroy' + articles.each(&:mark_as_deleted) + flash[:notice] = 'Alle gewählten Artikel wurden gelöscht' + when 'setNotAvailable' + articles.each {|a| a.update_attribute(:availability, false) } + flash[:notice] = 'Alle gewählten Artikel wurden auf "nicht verfügbar" gesetzt' + when 'setAvailable' + articles.each {|a| a.update_attribute(:availability, true) } + flash[:notice] = 'Alle gewählten Artikel wurden auf "verfügbar" gesetzt' + else + flash[:alert] = 'Keine Aktion ausgewählt!' + end end # action succeded redirect_to supplier_articles_url(@supplier, :per_page => params[:per_page]) - + rescue => error redirect_to supplier_articles_url(@supplier, :per_page => params[:per_page]), :alert => "Ein Fehler ist aufgetreten: #{error}" diff --git a/app/controllers/finance/ordergroups_controller.rb b/app/controllers/finance/ordergroups_controller.rb index 3b618e37..d4daeff6 100644 --- a/app/controllers/finance/ordergroups_controller.rb +++ b/app/controllers/finance/ordergroups_controller.rb @@ -12,7 +12,7 @@ class Finance::OrdergroupsController < Finance::BaseController sort = "name" end - @ordergroups = Ordergroup.order(sort) + @ordergroups = Ordergroup.undeleted.order(sort) @ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:query]}%") unless params[:query].nil? @ordergroups = @ordergroups.page(params[:page]).per(@per_page) diff --git a/app/controllers/foodcoop/ordergroups_controller.rb b/app/controllers/foodcoop/ordergroups_controller.rb index 0975b9a5..5391b798 100644 --- a/app/controllers/foodcoop/ordergroups_controller.rb +++ b/app/controllers/foodcoop/ordergroups_controller.rb @@ -1,7 +1,7 @@ class Foodcoop::OrdergroupsController < ApplicationController def index - @ordergroups = Ordergroup.order('name DESC') + @ordergroups = Ordergroup.undeleted.order('name DESC') unless params[:name].blank? # Search by name @ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:name]}%") diff --git a/app/controllers/stockit_controller.rb b/app/controllers/stockit_controller.rb index 2a232a31..03befe63 100644 --- a/app/controllers/stockit_controller.rb +++ b/app/controllers/stockit_controller.rb @@ -1,7 +1,7 @@ class StockitController < ApplicationController def index - @stock_articles = StockArticle.includes(:supplier, :article_category). + @stock_articles = StockArticle.undeleted.includes(:supplier, :article_category). order('suppliers.name, article_categories.name, articles.name') end @@ -33,7 +33,7 @@ class StockitController < ApplicationController def destroy @article = StockArticle.find(params[:id]) - @article.destroy + @article.mark_as_deleted render :layout => false rescue => error render :partial => "destroy_fail", :layout => false, diff --git a/app/controllers/suppliers_controller.rb b/app/controllers/suppliers_controller.rb index 5851c714..5a14e184 100644 --- a/app/controllers/suppliers_controller.rb +++ b/app/controllers/suppliers_controller.rb @@ -4,7 +4,7 @@ class SuppliersController < ApplicationController helper :deliveries def index - @suppliers = Supplier.order(:name) + @suppliers = Supplier.undeleted.order(:name) @deliveries = Delivery.recent end @@ -50,7 +50,7 @@ class SuppliersController < ApplicationController def destroy @supplier = Supplier.find(params[:id]) - @supplier.destroy + @supplier.mark_as_deleted flash[:notice] = "Lieferant wurde gelöscht" redirect_to suppliers_path rescue => e diff --git a/app/models/article.rb b/app/models/article.rb index 32554e84..852bed32 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -1,16 +1,16 @@ # encoding: utf-8 class Article < ActiveRecord::Base - acts_as_paranoid # Avoid deleting the article for consistency of order-results extend ActiveSupport::Memoizable # Ability to cache method results. Use memoize :expensive_method # Replace numeric seperator with database format localize_input_of :price, :tax, :deposit # Associations - belongs_to :supplier, :with_deleted => true + belongs_to :supplier belongs_to :article_category has_many :article_prices, :order => "created_at DESC" + scope :undeleted, -> { where(deleted_at: nil) } scope :available, :conditions => {:availability => true} scope :not_in_stock, :conditions => {:type => nil} @@ -136,6 +136,15 @@ class Article < ActiveRecord::Base end end + def deleted? + deleted_at.present? + end + + def mark_as_deleted + check_article_in_use + update_column :deleted_at, Time.now + end + protected # Checks if the article is in use before it will deleted diff --git a/app/models/article_price.rb b/app/models/article_price.rb index 686b891c..e946fc92 100644 --- a/app/models/article_price.rb +++ b/app/models/article_price.rb @@ -1,6 +1,6 @@ class ArticlePrice < ActiveRecord::Base - belongs_to :article, :with_deleted => true + belongs_to :article has_many :order_articles validates_presence_of :price, :tax, :deposit, :unit_quantity diff --git a/app/models/delivery.rb b/app/models/delivery.rb index b9c04616..3add6fdf 100644 --- a/app/models/delivery.rb +++ b/app/models/delivery.rb @@ -1,6 +1,6 @@ class Delivery < ActiveRecord::Base - belongs_to :supplier, :with_deleted => true + belongs_to :supplier has_one :invoice has_many :stock_changes, :dependent => :destroy diff --git a/app/models/financial_transaction.rb b/app/models/financial_transaction.rb index bdd7e48a..354a3d2a 100644 --- a/app/models/financial_transaction.rb +++ b/app/models/financial_transaction.rb @@ -1,7 +1,7 @@ # financial transactions are the foodcoop internal financial transactions # only ordergroups have an account balance and are happy to transfer money class FinancialTransaction < ActiveRecord::Base - belongs_to :ordergroup, :with_deleted => true + belongs_to :ordergroup belongs_to :user validates_presence_of :amount, :note, :user_id, :ordergroup_id diff --git a/app/models/group.rb b/app/models/group.rb index 68cb015c..092c0119 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -1,13 +1,15 @@ # Groups organize the User. # A Member gets the roles from the Group class Group < ActiveRecord::Base - has_many :memberships, :dependent => :destroy + has_many :memberships has_many :users, :through => :memberships validates :name, :presence => true, :length => {:in => 1..25} attr_reader :user_tokens - + + scope :undeleted, -> { where(deleted_at: nil) } + # Returns true if the given user if is an member of this group. def member?(user) memberships.find_by_user_id(user.id) @@ -21,7 +23,19 @@ class Group < ActiveRecord::Base def user_tokens=(ids) self.user_ids = ids.split(",") end - + + def deleted? + deleted_at.present? + end + + def mark_as_deleted + # TODO: Checks for participating in not closed orders + transaction do + memberships.destroy_all + # TODO: What should happen to users? + update_column :deleted_at, Time.now + end + end end diff --git a/app/models/group_order.rb b/app/models/group_order.rb index 04e69de7..35bec437 100644 --- a/app/models/group_order.rb +++ b/app/models/group_order.rb @@ -4,7 +4,7 @@ class GroupOrder < ActiveRecord::Base attr_accessor :group_order_articles_attributes belongs_to :order - belongs_to :ordergroup, :with_deleted => true + belongs_to :ordergroup has_many :group_order_articles, :dependent => :destroy has_many :order_articles, :through => :group_order_articles belongs_to :updated_by, :class_name => "User", :foreign_key => "updated_by_user_id" diff --git a/app/models/invoice.rb b/app/models/invoice.rb index a9f1d9ca..0feb3ede 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -1,6 +1,6 @@ class Invoice < ActiveRecord::Base - belongs_to :supplier, :with_deleted => true + belongs_to :supplier belongs_to :delivery belongs_to :order diff --git a/app/models/order.rb b/app/models/order.rb index 5afc166a..480df14a 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -10,7 +10,7 @@ class Order < ActiveRecord::Base has_one :invoice has_many :comments, :class_name => "OrderComment", :order => "created_at" has_many :stock_changes - belongs_to :supplier, :with_deleted => true + belongs_to :supplier belongs_to :updated_by, :class_name => 'User', :foreign_key => 'updated_by_user_id' belongs_to :created_by, :class_name => 'User', :foreign_key => 'created_by_user_id' diff --git a/app/models/order_article.rb b/app/models/order_article.rb index b68bfe82..af257f5d 100644 --- a/app/models/order_article.rb +++ b/app/models/order_article.rb @@ -4,7 +4,7 @@ class OrderArticle < ActiveRecord::Base attr_reader :update_current_price belongs_to :order - belongs_to :article, :with_deleted => true + belongs_to :article belongs_to :article_price has_many :group_order_articles, :dependent => :destroy diff --git a/app/models/ordergroup.rb b/app/models/ordergroup.rb index dbfe3171..ad1cffde 100644 --- a/app/models/ordergroup.rb +++ b/app/models/ordergroup.rb @@ -8,7 +8,6 @@ class Ordergroup < Group APPLE_MONTH_AGO = 6 # How many month back we will count tasks and orders sum - acts_as_paranoid # Avoid deleting the ordergroup for consistency of order-results serialize :stats has_many :financial_transactions @@ -110,7 +109,7 @@ 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? ? '' : self.id - group = Ordergroup.with_deleted.where('groups.id != ? AND groups.name = ?', id, name).first + group = Ordergroup.where('groups.id != ? AND groups.name = ?', id, name).first if group.present? message = group.deleted? ? :taken_with_deleted : :taken errors.add :name, message diff --git a/app/models/stock_article.rb b/app/models/stock_article.rb index 6050c8c4..21c8bb56 100644 --- a/app/models/stock_article.rb +++ b/app/models/stock_article.rb @@ -1,10 +1,9 @@ # encoding: utf-8 class StockArticle < Article - acts_as_paranoid - + has_many :stock_changes - scope :available, :conditions => "quantity > 0" + scope :available, -> { undeleted.where'quantity > 0' } before_destroy :check_quantity @@ -23,6 +22,11 @@ class StockArticle < Article available.collect { |a| a.quantity * a.gross_price }.sum end + def mark_as_deleted + check_quantity + super + end + protected def check_quantity diff --git a/app/models/stock_change.rb b/app/models/stock_change.rb index 029b92b6..6a7adc75 100644 --- a/app/models/stock_change.rb +++ b/app/models/stock_change.rb @@ -1,7 +1,7 @@ class StockChange < ActiveRecord::Base belongs_to :delivery belongs_to :order - belongs_to :stock_article, with_deleted: true + belongs_to :stock_article validates_presence_of :stock_article_id, :quantity validates_numericality_of :quantity diff --git a/app/models/supplier.rb b/app/models/supplier.rb index 384c5973..557cd4e4 100644 --- a/app/models/supplier.rb +++ b/app/models/supplier.rb @@ -1,7 +1,7 @@ +# encoding: utf-8 class Supplier < ActiveRecord::Base - acts_as_paranoid # Avoid deleting the supplier for consistency of order-results - has_many :articles, :dependent => :destroy, :conditions => {:type => nil}, + has_many :articles, :conditions => {:type => nil}, :include => [:article_category], :order => 'article_categories.name, articles.name' has_many :stock_articles, :include => [:article_category], :order => 'article_categories.name, articles.name' has_many :orders @@ -20,13 +20,15 @@ class Supplier < ActiveRecord::Base validates_length_of :address, :in => 8..50 validate :uniqueness_of_name + scope :undeleted, -> { where(deleted_at: nil) } + # sync all articles with the external database # returns an array with articles(and prices), which should be updated (to use in a form) # also returns an array with outlisted_articles, which should be deleted def sync_all updated_articles = Array.new outlisted_articles = Array.new - for article in articles + for article in articles.undeleted # try to find the associated shared_article shared_article = article.shared_article @@ -65,12 +67,23 @@ class Supplier < ActiveRecord::Base return [updated_articles, outlisted_articles] end + def deleted? + deleted_at.present? + end + + def mark_as_deleted + transaction do + update_column :deleted_at, Time.now + articles.each(&:mark_as_deleted) + end + end + protected # Make sure, the name is uniq, add usefull message if uniq group is already deleted def uniqueness_of_name id = new_record? ? '' : self.id - supplier = Supplier.with_deleted.where('suppliers.id != ? AND suppliers.name = ?', id, name).first + supplier = Supplier.where('suppliers.id != ? AND suppliers.name = ?', id, name).first if supplier.present? message = supplier.deleted? ? :taken_with_deleted : :taken errors.add :name, message diff --git a/app/views/articles/index.haml b/app/views/articles/index.haml index be976bd5..5c8946ee 100644 --- a/app/views/articles/index.haml +++ b/app/views/articles/index.haml @@ -1,4 +1,4 @@ -- title "Artikel von #{@supplier.name} (#{@supplier.articles.count})" +- title "Artikel von #{@supplier.name} (#{@supplier.articles.undeleted.count})" .well.well-small .btn-toolbar @@ -28,7 +28,7 @@ Lieferant wechseln .. %span.caret %ul.dropdown-menu - - Supplier.where('id != ?', @supplier.id).order('name ASC').each do |supplier| + - Supplier.undeleted.where('id != ?', @supplier.id).order('suppliers.name ASC').each do |supplier| %li= link_to supplier.name, supplier_articles_path(supplier), tabindex: -1 - unless @supplier.shared_supplier.nil? diff --git a/app/views/messages/new.haml b/app/views/messages/new.haml index 965bf7a5..36f70970 100644 --- a/app/views/messages/new.haml +++ b/app/views/messages/new.haml @@ -41,7 +41,7 @@ #recipients = f.input :recipient_tokens, :input_html => { 'data-pre' => User.find_all_by_id(@message.recipients_ids).map { |u| u.token_attributes }.to_json } - = f.input :group_id, :as => :select, :collection => Group.order('type DESC, name ASC').all.reject { |g| g.memberships.empty? } + = f.input :group_id, :as => :select, :collection => Group.undeleted.order('type DESC, name ASC').all.reject { |g| g.memberships.empty? } = f.input :private = f.input :subject, input_html: {class: 'input-xxlarge'} = f.input :body, input_html: {class: 'input-xxlarge'} diff --git a/app/views/orders/index.html.haml b/app/views/orders/index.html.haml index 1ebe04f0..4180c96d 100644 --- a/app/views/orders/index.html.haml +++ b/app/views/orders/index.html.haml @@ -6,7 +6,7 @@ Neue Bestellung anlegen %span.caret %ul.dropdown-menu - - Supplier.all.each do |supplier| + - Supplier.undeleted.order('suppliers.name ASC').each do |supplier| %li= link_to supplier.name, new_order_path(supplier_id: supplier.id), tabindex: -1 .well diff --git a/app/views/suppliers/index.haml b/app/views/suppliers/index.haml index 4697f573..bb9a3e0f 100644 --- a/app/views/suppliers/index.haml +++ b/app/views/suppliers/index.haml @@ -18,8 +18,8 @@ %td= link_to h(supplier.name) , supplier %td= supplier.phone %td= supplier.customer_number - %td= link_to "Artikel (#{supplier.articles.count})", supplier_articles_path(supplier) - %td= link_to "im Lager (#{supplier.stock_articles.count})", stock_articles_path + %td= link_to "Artikel (#{supplier.articles.undeleted.count})", supplier_articles_path(supplier) + %td= link_to "im Lager (#{supplier.stock_articles.undeleted.count})", stock_articles_path %td= link_to "Lieferungen (#{supplier.deliveries.count})", supplier_deliveries_path(supplier) %td = link_to "Bearbeiten", edit_supplier_path(supplier), class: 'btn btn-mini'