From fc1c173718e8769f08fc7f87764818deb4bf18d5 Mon Sep 17 00:00:00 2001 From: benni Date: Sun, 28 Oct 2012 18:03:50 +0100 Subject: [PATCH] Fixed articles module. --- Gemfile | 1 - Gemfile.lock | 2 - app/assets/javascripts/application.js | 6 +- .../bootstrap_and_overrides.css.less | 18 ++++++ app/controllers/articles_controller.rb | 43 +++++++------ app/helpers/articles_helper.rb | 8 +-- app/models/article.rb | 2 +- app/views/articles/_article.html.haml | 11 ++-- app/views/articles/_edit_all_table.html.haml | 34 ++++++++++ app/views/articles/edit_all.html.erb | 62 ------------------- app/views/articles/edit_all.html.haml | 11 ++++ app/views/articles/parse_upload.html.haml | 35 ++--------- app/views/articles/upload.html.haml | 32 +++++----- lib/foodsoft_file.rb | 6 +- 14 files changed, 124 insertions(+), 147 deletions(-) create mode 100644 app/views/articles/_edit_all_table.html.haml delete mode 100644 app/views/articles/edit_all.html.erb create mode 100644 app/views/articles/edit_all.html.haml diff --git a/Gemfile b/Gemfile index d5c1c3d7..aef7e70b 100644 --- a/Gemfile +++ b/Gemfile @@ -18,7 +18,6 @@ end gem 'jquery-rails' gem 'mysql2' -gem "fastercsv" gem 'prawn' gem 'haml-rails' gem 'kaminari' diff --git a/Gemfile.lock b/Gemfile.lock index cd253630..352a627f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -58,7 +58,6 @@ GEM execjs (1.4.0) multi_json (~> 1.0) expression_parser (0.9.0) - fastercsv (1.5.5) haml (3.1.7) haml-rails (0.3.5) actionpack (>= 3.1, < 4.1) @@ -184,7 +183,6 @@ DEPENDENCIES daemons delayed_job_active_record exception_notification - fastercsv haml-rails inherited_resources jquery-rails diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index eacedaac..8872d4de 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -46,8 +46,10 @@ $(function() { // Submit form when changing a select menu. $('form[data-submit-onchange] select').live('change', function() { var confirmMessage = $(this).children(':selected').data('confirm'); - if (confirmMessage && confirm(confirmMessage)) { - $(this).parents('form').submit(); + if (confirmMessage) { + if (confirm(confirmMessage)) { + $(this).parents('form').submit(); + } } else { $(this).parents('form').submit(); } diff --git a/app/assets/stylesheets/bootstrap_and_overrides.css.less b/app/assets/stylesheets/bootstrap_and_overrides.css.less index d9b5605d..0dec3b9b 100644 --- a/app/assets/stylesheets/bootstrap_and_overrides.css.less +++ b/app/assets/stylesheets/bootstrap_and_overrides.css.less @@ -154,3 +154,21 @@ tr.order-article .article-info { tr.order-article:hover .article-info { display: block; } + + +// ********* Articles + +tr.just-updated { + color: #468847; +} + +tr.unavailable { + color: #999; +} + +// articles edit all +.field_with_errors { + input, select { + border-color: red; + } +} \ No newline at end of file diff --git a/app/controllers/articles_controller.rb b/app/controllers/articles_controller.rb index 9ee5039d..38f70c2e 100644 --- a/app/controllers/articles_controller.rb +++ b/app/controllers/articles_controller.rb @@ -76,15 +76,19 @@ class ArticlesController < ApplicationController # 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 unless params[:articles].blank? + invalid_articles = false # Update other article attributes... - for id, attributes in params[:articles] - currentArticle = Article.find(id) - currentArticle.update_attributes!(attributes) + @articles = Article.find(params[:articles].keys) + @articles.each do |article| + unless article.update_attributes(params[:articles][article.id.to_s]) + invalid_articles = true unless invalid_articles # Remember that there are validation errors + end end + + raise "Artikel sind fehlerhaft. Bitte überprüfe Deine Eingaben." if invalid_articles end # delete articles if params[:outlisted_articles] @@ -92,18 +96,16 @@ class ArticlesController < ApplicationController end end # Successfully done. - flash[:notice] = 'Alle Artikel und Preise wurden aktalisiert' - redirect_to supplier_articles_path(@supplier) + redirect_to supplier_articles_path(@supplier), notice: "Alle Artikel und Preise wurden aktalisiert" 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(supplier_articles_path(@supplier)) : render(:action => 'edit_all') + if params[:sync] + flash[:error] = "Es trat ein Fehler beim Aktualisieren des Artikels '#{current_article.name}' auf: #{e.message}" + redirect_to(supplier_articles_path(@supplier)) else - flash[:error] = "Es trat ein Fehler beim Aktualisieren der Artikel auf: #{e.message}" - redirect_to supplier_articles_path(@supplier) + flash.now.alert = e.message + render :edit_all end end end @@ -178,17 +180,22 @@ class ArticlesController < ApplicationController def create_from_upload begin Article.transaction do - for article_attributes in params[:articles] - @supplier.articles.create!(article_attributes) + invalid_articles = false + @articles = [] + params[:articles].each do |_key, article_attributes| + @articles << (article = @supplier.articles.build(article_attributes)) + invalid_articles = true unless article.save end + + raise "Artikel sind fehlerhaft" if invalid_articles end # Successfully done. - flash[:notice] = "The articles are saved successfully" - redirect_to supplier_articles_path(@supplier) + redirect_to supplier_articles_path(@supplier), notice: "Es wurden #{@articles.size} neue Artikel gespeichert." + rescue => error # An error has occurred, transaction has been rolled back. - flash[:error] = "An error occured: #{error.message}" - redirect_to upload_supplier_articles_path(@supplier) + flash.now[:error] = "An error occured: #{error.message}" + render :parse_upload end end diff --git a/app/helpers/articles_helper.rb b/app/helpers/articles_helper.rb index 44f1d0d6..ee8f58e1 100644 --- a/app/helpers/articles_helper.rb +++ b/app/helpers/articles_helper.rb @@ -6,10 +6,10 @@ module ArticlesHelper end def row_classes(article) - classes = " " - classes += " unavailable" if !article.availability - classes += " just_updated" if article.recently_updated && article.availability - classes + classes = [] + classes << "unavailable" if !article.availability + classes << "just-updated" if article.recently_updated && article.availability + classes.join(" ") end # Flatten search params, used in import from external database diff --git a/app/models/article.rb b/app/models/article.rb index 3c961058..09f17fa4 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -15,7 +15,7 @@ class Article < ActiveRecord::Base scope :not_in_stock, :conditions => {:type => nil} # Validations - validates_presence_of :name, :unit, :price, :tax, :deposit, :unit_quantity, :supplier_id, :article_category_id + validates_presence_of :name, :unit, :price, :tax, :deposit, :unit_quantity, :supplier_id, :article_category validates_length_of :name, :in => 4..60 validates_length_of :unit, :in => 2..15 validates_numericality_of :price, :unit_quantity, :greater_than => 0 diff --git a/app/views/articles/_article.html.haml b/app/views/articles/_article.html.haml index 2f4fa38c..ac2679e1 100644 --- a/app/views/articles/_article.html.haml +++ b/app/views/articles/_article.html.haml @@ -1,4 +1,4 @@ -%tr{ :class => cycle('even','odd') + row_classes(article)}[article] +%tr{class: row_classes(article)} %td= check_box_tag 'selected_articles[]', article.id.to_s, false, {:id => "checkbox_#{article.id}", 'data-ignore-onchange' => true} %td{'data-check-this' => "#checkbox_#{article.id}", :class => 'click-me'}= article.name %td= article.origin @@ -11,10 +11,9 @@ = number_to_currency(article.price) %td= number_to_percentage(article.tax) if article.tax != 0 %td= number_to_currency(article.deposit) if article.deposit != 0 - %td - = link_to icon(:edit), edit_supplier_article_path(@supplier, article), - :remote => true - = link_to icon(:delete), [@supplier, article], - :method => :delete, :confirm => 'Bist du sicher?', :remote => true + %td= link_to "Bearbeiten", edit_supplier_article_path(@supplier, article), + :remote => true, class: 'btn btn-mini' + %td= link_to "Löschen", [@supplier, article], + :method => :delete, :confirm => 'Bist du sicher?', :remote => true, class: 'btn btn-mini btn-danger' \ No newline at end of file diff --git a/app/views/articles/_edit_all_table.html.haml b/app/views/articles/_edit_all_table.html.haml new file mode 100644 index 00000000..3189b27b --- /dev/null +++ b/app/views/articles/_edit_all_table.html.haml @@ -0,0 +1,34 @@ +%table.table + %thead + %tr + %th + %acronym{:title => "verfügbar"} verf. + %th Name + %th Einheit + %th + %acronym{:title => "Netto!"} Preis + %th + %acronym{:title => "Gebindegröße"} GebGr + %th Best.Nr. + %th Notiz + %th Kategorie + %th MwSt. + %th Pfand + %tbody + - @articles.each_with_index do |article, index| + = fields_for "articles[#{article.id || index}]", article do |form| + %tr + %td= form.check_box 'availability' + %td= form.text_field 'name', class: 'input-medium' + %td= form.text_field 'unit', class: 'input-mini' + %td= form.text_field 'price', class: 'input-mini' + %td= form.text_field 'unit_quantity', class: 'input-mini' + %td= form.text_field 'order_number', class: 'input-mini' + %td= form.text_field 'note', class: 'input-medium' + %td= form.collection_select 'article_category_id', ArticleCategory.all, + :id, :name, { :include_blank => true }, class: 'input-small' + %td= form.text_field 'tax', class: 'input-mini' + %td= form.text_field 'deposit', class: 'input-mini' + - unless article.errors.empty? + %tr.alert + %td(colspan="10")= article.errors.full_messages.join(", ") \ No newline at end of file diff --git a/app/views/articles/edit_all.html.erb b/app/views/articles/edit_all.html.erb deleted file mode 100644 index 40147f63..00000000 --- a/app/views/articles/edit_all.html.erb +++ /dev/null @@ -1,62 +0,0 @@ -<% title "Alle Artikel von #{@supplier.name} bearbeiten" %> - -
-
- <%= select_tag :switch_supplier, - options_for_select( Supplier.all.collect {|s| [s.name, edit_all_supplier_articles_url(s)] }, - edit_all_supplier_articles_url(@supplier)), - 'data-redirect-to' => true, - :style => "font-size: 0.9em;margin-left:1em;" %> -
-
-

-
-
- -

- - Pflichtfelder sind: Name, Einheit, (netto) Preis und Bestellnummer. - -

- <%= form_tag(update_all_supplier_articles_path(@supplier)) do %> - - - - - - - - - - - - - - - - <% for article in @articles %> - <%= fields_for 'articles[]', article do |form| %> - > - - - - - - - - - - - <% end %> - <% end %> - - -
verf.NameEinheitPreisGebGrBest.Nr.NotizKategorieMwSt.Pfand
- <%= form.check_box 'availability' -%> - <%= form.text_field 'name', :size => 0 -%> - <%= form.text_field 'unit', :size => 5 -%><%= form.text_field 'price', :size => 4 -%><%= form.text_field 'unit_quantity', :size => 4 -%><%= form.text_field 'order_number', :size => 6 -%><%= form.text_field 'note', :size => 15 -%><%= form.select 'article_category_id', ArticleCategory.find(:all).collect {|a| [ a.name, a.id ] }, { :include_blank => true } -%><%= form.text_field 'tax', :size => 4 -%><%= form.text_field 'deposit', :size => 4 -%>

- Achtung, alle Artikel werden aktualisiert!
- <%= submit_tag 'Alle Artikel aktualisieren'%> | <%= link_to 'Abbrechen', supplier_articles_path(@supplier) %> - <% end %> -
-
\ No newline at end of file diff --git a/app/views/articles/edit_all.html.haml b/app/views/articles/edit_all.html.haml new file mode 100644 index 00000000..a9668218 --- /dev/null +++ b/app/views/articles/edit_all.html.haml @@ -0,0 +1,11 @@ +- title "Alle Artikel von #{@supplier.name} bearbeiten" | +%p + %i + Pflichtfelder sind: Name, Einheit, (netto) Preis und Bestellnummer. += form_tag(update_all_supplier_articles_path(@supplier)) do + = render 'edit_all_table' + %br/ + %i Achtung, alle Artikel werden aktualisiert! + .form-actions + = submit_tag 'Alle Artikel aktualisieren', class: 'btn btn-primary' + = link_to 'oder abbrechen', supplier_articles_path(@supplier) diff --git a/app/views/articles/parse_upload.html.haml b/app/views/articles/parse_upload.html.haml index 78052fb9..fede8550 100644 --- a/app/views/articles/parse_upload.html.haml +++ b/app/views/articles/parse_upload.html.haml @@ -6,35 +6,8 @@ Achtung, momentan gibt es keine Überprüfung auf doppelte Artikel. = form_tag(create_from_upload_supplier_articles_path(@supplier)) do - %table - %tr - %th Nummer - %th Name - %th Notiz - %th Hersteller - %th Herkunft - %th Einheit - %th Nettopreis - %th MwSt - %th Pfand - %th Gebindegröße - %th Kategorie - - for article in @articles - = fields_for "articles[]", article do |form| - %tr{:class => cycle('even', 'odd')} - %td= form.text_field 'order_number', :size => 6 - %td= form.text_field 'name', :size => 0 - %td= form.text_field 'note', :size => 15 - %td= form.text_field 'manufacturer', :size => 6 - %td= form.text_field 'origin', :size => 6 - %td= form.text_field 'unit', :size => 5 - %td= form.text_field 'price', :size => 4 - %td= form.text_field 'tax', :size => 4 - %td= form.text_field 'deposit', :size => 4 - %td= form.text_field 'unit_quantity', :size => 4 - %td= form.select 'article_category_id', ArticleCategory.find(:all).collect {|a| [ a.name, a.id ] } - %p - = submit_tag "Speichere neue Artikel für #{@supplier.name}" - | - = link_to "Zurück", upload_supplier_articles_path(@supplier) + = render 'edit_all_table' + .form-actions + = submit_tag "Speichere neue Artikel für #{@supplier.name}", class: 'btn btn-primary' + = link_to "order abbrechen", upload_supplier_articles_path(@supplier) \ No newline at end of file diff --git a/app/views/articles/upload.html.haml b/app/views/articles/upload.html.haml index dcb3bfe2..9ddc66f7 100644 --- a/app/views/articles/upload.html.haml +++ b/app/views/articles/upload.html.haml @@ -1,23 +1,21 @@ - title "#{@supplier.name} / Artikel hochladen" %p - %i - Die Datei muss eine Textdatei mit der Endung '.csv' sein. Die erste Zeile - wird beim Einlesen ignoriert. - %br/ - Die Felder müssen mit einem Semikolon (';') getrennt und der Text mit doppelten - Anführungszeichen ("Text...") umklammert werden. - %br/ - Als Zeichensatz wird UTF-8 erwartet. -%p - %i - Korrekte Reihenfolge der Spalten: - %br/ + Die Datei muss eine Textdatei mit der Endung '.csv' sein. Die erste Zeile + wird beim Einlesen ignoriert. + %br/ + Die Felder müssen mit einem Semikolon (';') getrennt und der Text mit doppelten + Anführungszeichen ("Text...") umklammert werden. + %br/ + Als Zeichensatz wird UTF-8 erwartet. Korrekte Reihenfolge der Spalten: + %pre = ["Status (x=ausgelistet)", "Bestellnummer", "Name", "Notiz", "Hersteller", "Herkunft", "Einheit", "Preis(netto)", "MwSt", "Pfand", "Gebindegröße", "Staffelmenge", "Staffelpreis", "Kategorie"].join(" | ") -#uploadArticles.uploadForm - = form_for :articles, :url => parse_upload_supplier_articles_path(@supplier), - :html => { :multipart => true } do |form| - %p= form.file_field "file" - %p= submit_tag "Datei hochladen" += form_for :articles, :url => parse_upload_supplier_articles_path(@supplier), + :html => { :multipart => true } do |f| + %label(for="articles_file") + Bitte wähle eine kompatible Datei aus + = f.file_field "file" + .form-actions + = submit_tag "Datei hochladen", class: 'btn' diff --git a/lib/foodsoft_file.rb b/lib/foodsoft_file.rb index 594c0ed9..1aa40dfb 100644 --- a/lib/foodsoft_file.rb +++ b/lib/foodsoft_file.rb @@ -1,7 +1,7 @@ # Module for FoodSoft-File import # The FoodSoft-File is a cvs-file, with semicolon-seperatet columns - -require 'faster_csv' + +require 'csv' module FoodsoftFile @@ -11,7 +11,7 @@ module FoodsoftFile def self.parse(file) articles, outlisted_articles = Array.new, Array.new row_index = 2 - FasterCSV.parse(file.read, {:col_sep => ";", :headers => true}) do |row| + ::CSV.parse(file.read, {:col_sep => ";", :headers => true}) do |row| # check if the line is empty unless row[2] == "" || row[2].nil? article = {:number => row[1],