foodsoft/app/controllers/articles_controller.rb

418 lines
15 KiB
Ruby

class ArticlesController < ApplicationController
before_filter :authenticate_article_meta
verify :method => :post,
:only => [ :destroyArticle, :createArticle, :updateArticle,
:update_all, :createArticlesFromFile, :update_selected_articles ],
:redirect_to => { :action => :list }
# messages
ERROR_NO_SELECTED_ARTICLES = 'Du hast keine Artikel ausgewählt'
MSG_ALL_CHECKED_DESTROYED = 'Alle gewählten Artikel wurden gelöscht'
MSG_ALL_CHECKED_UNAVAILABLE = 'Alle gewählten Artikel wurden auf "nicht verfügbar" gesetzt'
MSG_ALL_CHECKED_AVAILABLE = 'Alle gewählten Artikel wurden auf "verfügbar" gesetzt'
ERROR_NO_SELECTED_ACTION = 'Keine Aktion ausgewählt!'
ERROR_UPDATE_ARTICLES = 'Ein Fehler ist aufgetreten: '
def index
@suppliers = Supplier.find(:all)
end
def list
if params[:id]
@supplier = Supplier.find(params[:id])
@suppliers = Supplier.find(:all)
if (params[:per_page] && params[:per_page].to_i > 0 && params[:per_page].to_i <= 500)
@per_page = params[:per_page].to_i
else
@per_page = 30
end
if params['sort']
sort = case params['sort']
when "name" then "articles.name"
when "unit" then "articles.unit"
when "category" then "article_categories.name"
when "note" then "articles.note"
when "availability" then "articles.availability"
when "name_reverse" then "articles.name DESC"
when "unit_reverse" then "articles.unit DESC"
when "category_reverse" then "article_categories.name DESC"
when "note_reverse" then "articles.note DESC"
when "availability_reverse" then "articles.availability DESC"
end
else
sort = "article_categories.name, articles.name"
end
# if somebody uses the search field:
conditions = ["articles.name LIKE ?", "%#{params[:query]}%"] unless params[:query].nil?
@total = @supplier.articles.count(:conditions => conditions)
@articles = @supplier.articles.paginate(:order => sort,
:conditions => conditions,
:page => params[:page],
:per_page => @per_page,
:include => :article_category)
respond_to do |format|
format.html # list.haml
format.js do
render :update do |page|
page.replace_html 'table', :partial => "list"
end
end
end
else
redirect_to :action => 'index'
end
end
def newArticle
@supplier = Supplier.find(params[:supplier])
@article = Article.new(:supplier => @supplier, :tax => 7.0)
render :update do |page|
page["edit_article"].replace_html :partial => 'new'
page["edit_article"].show
end
end
def createArticle
@article = Article.new(params[:article])
if @article.valid? and @article.save
render :update do |page|
page.Element.hide('edit_article')
page.insert_html :top, 'listbody', :partial => 'new_article_row'
page[@article.id.to_s].visual_effect(:highlight,
:duration => 2)
# highlights article
if !@article.availability
page[@article.id.to_s].addClassName 'unavailable'
else
page[@article.id.to_s].addClassName 'just_updated'
end
end
else
render :update do |page|
page.replace_html 'edit_article', :partial => "new"
end
end
end
# edit an article and its price
def editArticle
@article = Article.find(params[:id])
render :update do |page|
page["edit_article"].replace_html :partial => 'edit'
page["edit_article"].show
end
#render :partial => "quick_edit", :layout => false
end
# Updates one Article and highlights the line if succeded
def updateArticle
@article = Article.find(params[:id])
if @article.update_attributes(params[:article])
render :update do |page|
page["edit_article"].hide
page[@article.id.to_s].replace_html :partial => 'article_row'
# hilights an updated article if the article ist available
page[@article.id.to_s].addClassName 'just_updated' if @article.availability
# highlights an available article and de-highlights in other case
if !@article.availability
page[@article.id.to_s].addClassName 'unavailable'
# remove updated-class
page[@article.id.to_s].removeClassName 'just_updated'
else
page[@article.id.to_s].removeClassName 'unavailable'
end
page[@article.id.to_s].visual_effect(:highlight, :delay => 0.5, :duration => 2)
end
else
render :update do |page|
page["edit_article"].replace_html :partial => "edit"
end
end
end
# Deletes article from database. send error msg, if article is used in a current order
def destroyArticle
@article = Article.find(params[:id])
@order = @article.inUse #if article is in an active Order, the Order will be returned
if @order
render :update do |page|
page.insert_html :after, @article.id.to_s, :partial => 'destroyActiveArticle'
end
else
@article.destroy
render :update do |page|
page[@article.id.to_s].remove
end
end
end
# Renders a form for editing all articles from a supplier
def edit_all
@supplier = Supplier.find(params[:id])
end
# Updates all article of specific supplier
# deletes all articles from params[outlisted_articles]
def update_all
currentArticle = nil # used to find out which article caused a validation exception
begin
Article.transaction do
@supplier = Supplier.find(params[:supplier][:id]) if params[:supplier][:id]
unless params[:article].blank?
# Update other article attributes...
i = 0
for id in params[:article].keys
currentArticle = Article.find(id)
currentArticle.update_attributes!(params[:article].values[i])
i += 1
end
end
# delete articles
if params[:outlisted_articles]
params[:outlisted_articles].keys.each {|id| Article.find(id).destroy }
end
end
# Successfully done.
flash[:notice] = 'Alle Artikel und Preise wurden aktalisiert'
redirect_to :action => 'list', :id => @supplier
rescue => e
# An error has occurred, transaction has been rolled back.
if currentArticle
@failedArticle = currentArticle
flash[:error] = "Es trat ein Fehler beim Aktualisieren des Artikels '#{currentArticle.name}' auf: #{e.message}"
params[:sync] ? redirect_to(:action => "list", :id => @supplier) : render(:action => 'edit_all')
else
flash[:error] = "Es trat ein Fehler beim Aktualisieren der Artikel auf: #{e.message}"
redirect_to :action => "index"
end
end
end
# makes different actions on selected articles
def update_selected_articles
@supplier = Supplier.find(params[:supplier])
articles = Array.new
begin
raise ERROR_NO_SELECTED_ARTICLES if params[:selected_articles].nil?
params[:selected_articles].each do |article|
articles << Article.find(article) # put selected articles in an array
end
case params[:selected_action].to_s
when 'destroy'
articles.each {|a| a.destroy }
flash[:notice] = MSG_ALL_CHECKED_DESTROYED
when 'setNotAvailable'
articles.each {|a| a.update_attribute(:availability, false) }
flash[:notice] = MSG_ALL_CHECKED_UNAVAILABLE
when 'setAvailable'
articles.each {|a| a.update_attribute(:availability, true) }
flash[:notice] = MSG_ALL_CHECKED_AVAILABLE
else
flash[:error] = ERROR_NO_SELECTED_ACTION
end
# action succeded
redirect_to :action => 'list', :id => @supplier
rescue => e
flash[:error] = ERROR_UPDATE_ARTICLES + e
redirect_to :action => 'list', :id => @supplier
end
end
#************** start article categories ************************
def newCategory
@article_category = ArticleCategory.new
render :update do |page|
page['category_form'].replace_html :partial => 'article_categories/new'
page['category_form'].show
end
end
def createCategory
@article_category = ArticleCategory.new(params[:article_category])
if @article_category.save
render :update do |page|
page['category_form'].hide
page['category_list'].replace_html :partial => 'article_categories/list'
page['category_'+@article_category.id.to_s].visual_effect(:highlight,
:duration => 2)
end
else
render :update do |page|
page['category_form'].replace_html :partial => 'article_categories/new'
end
end
end
def editCategory
@article_category = ArticleCategory.find(params[:id])
render :update do |page|
page['category_form'].replace_html :partial => 'article_categories/edit'
page['category_form'].show
end
end
def updateCategory
@article_category = ArticleCategory.find(params[:id])
if @article_category.update_attributes(params[:article_category])
render :update do |page|
page['category_form'].hide
page['category_list'].replace_html :partial => 'article_categories/list'
page['category_'+@article_category.id.to_s].visual_effect(:highlight,
:duration => 2)
end
else
render :update do |page|
page['category_form'].replace_html :partial => 'article_categories/edit'
end
end
end
def destroyCategory
@article_category = ArticleCategory.find(params[:id])
id = @article_category.id.to_s #save the id before destroying the object
if @article_category.destroy
render :update do |page|
page['category_'+id].visual_effect :drop_out
end
end
end
# lets start with parsing articles from uploaded file, yeah
# Renders the upload form
def upload_articles
end
# parses the articles from a csv and creates a form-table with the parsed data.
# the csv must have the following format:
# status | number | name | note | manufacturer | origin | unit | clear price | unit_quantity | tax | deposit | scale quantity | scale price | category
# the first line will be ignored.
# field-seperator: ";"
# text-seperator: ""
def parse_articles
begin
@articles = Array.new
articles, outlisted_articles = FoodsoftFile::parse(params[:articles]["file"])
articles.each do |row|
# creates a new article and price
article = Article.new( :name => row[:name],
:note => row[:note],
:manufacturer => row[:manufacturer],
:origin => row[:origin],
:unit => row[:unit],
:article_category => ArticleCategory.find_by_name(row[:category]),
:net_price => row[:price],
:unit_quantity => row[:unit_quantity],
:order_number => row[:number],
:deposit => row[:deposit],
:tax => row[:tax])
# stop parsing, when an article isn't valid
unless article.valid?
raise article.errors.full_messages.join(", ") + _(" ..in line ") + (articles.index(row) + 2).to_s
end
@articles << article
end
flash.now[:notice] = @articles.size.to_s + _(" articles are parsed successfully.")
rescue => e
flash[:error] = _("An error has occurred: ") + e.message
redirect_to :action => 'upload_articles'
end
end
# creates articles from form
def create_articles_from_file
@supplier = Supplier.find(params[:supplier][:id])
begin
Article.transaction do
i = 0
params[:article].each do
@article = Article.new(params[:article][i])
@article.supplier = @supplier
@article.save!
i += 1
end
end
# Successfully done.
flash[:notice] = _("The articles are saved successfully")
redirect_to :action => 'list', :id => @supplier
rescue => e
# An error has occurred, transaction has been rolled back.
flash[:error] = _("An error occured: ") + " #{e.message}"
redirect_to :action => 'upload_articles'
end
end
# renders a view to import articles in local database
#
def list_shared_articles
@supplier = Supplier.find(params[:id])
conditions = []
conditions << "supplier_id = #{@supplier.shared_supplier.id}"
# check for keywords
conditions << params[:import_query].split(' ').collect { |keyword| "name LIKE '%#{keyword}%'" }.join(' AND ') unless params[:import_query].blank?
# check for selected lists
conditions << "(" + params[:lists].collect {|list| "list = '#{list[0]}'"}.join(" OR ") + ")" if params[:lists]
# check for regional articles
conditions << "origin = 'REG'" if params[:regional]
@articles = SharedArticle.paginate :page => params[:page], :per_page => 10, :conditions => conditions.join(" AND ")
render :update do |page|
page.replace_html 'search_results', :partial => "import_search_results"
end
end
# fills a form whith values of the selected shared_article
def new_import
shared_article = SharedArticle.find(params[:id])
@article = Article.new(
:supplier_id => params[:supplier_id],
:name => shared_article.name,
:unit => shared_article.unit,
:note => shared_article.note,
:manufacturer => shared_article.manufacturer,
:origin => shared_article.origin,
:net_price => shared_article.price,
:tax => shared_article.tax,
:deposit => shared_article.deposit,
:unit_quantity => shared_article.unit_quantity,
:order_number => shared_article.number,
# convert to db-compatible-string
:shared_updated_on => shared_article.updated_on.to_formatted_s(:db))
render :update do |page|
page["edit_article"].replace_html :partial => 'new'
page["edit_article"].show
end
end
# sync all articles with the external database
# renders a form with articles, which should be updated
def sync_articles
@supplier = Supplier.find(params[:id])
# check if there is an shared_supplier
unless @supplier.shared_supplier
flash[:error]= @supplier.name + _(" ist not assigned to an external database.")
redirect_to :action => "list", :id => @supplier
end
# sync articles against external database
@updated_articles, @outlisted_articles = @supplier.sync_all
# convert to db-compatible-string
@updated_articles.each {|a, b| a.shared_updated_on = a.shared_updated_on.to_formatted_s(:db)}
if @updated_articles.empty? && @outlisted_articles.empty?
flash[:notice] = _("The database is up to date.")
redirect_to :action => 'list', :id => @supplier
end
end
end