diff --git a/app/controllers/stockit_controller.rb b/app/controllers/stockit_controller.rb index 9ee40efe..3e3b43b2 100644 --- a/app/controllers/stockit_controller.rb +++ b/app/controllers/stockit_controller.rb @@ -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 diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb index 16fc0f73..ee4c05cd 100644 --- a/app/controllers/tasks_controller.rb +++ b/app/controllers/tasks_controller.rb @@ -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') diff --git a/app/helpers/stockit_helper.rb b/app/helpers/stockit_helper.rb index 2888603c..f6a0a1fc 100644 --- a/app/helpers/stockit_helper.rb +++ b/app/helpers/stockit_helper.rb @@ -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 diff --git a/app/models/periodic_task_group.rb b/app/models/periodic_task_group.rb new file mode 100644 index 00000000..b92de76c --- /dev/null +++ b/app/models/periodic_task_group.rb @@ -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 diff --git a/app/models/stock_article.rb b/app/models/stock_article.rb index 0124219a..5d45802e 100644 --- a/app/models/stock_article.rb +++ b/app/models/stock_article.rb @@ -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 diff --git a/app/models/stock_change.rb b/app/models/stock_change.rb index 6a7adc75..9c4bf082 100644 --- a/app/models/stock_change.rb +++ b/app/models/stock_change.rb @@ -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 diff --git a/app/models/task.rb b/app/models/task.rb index 64c5ff20..bd2f23d6 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -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 diff --git a/app/models/workgroup.rb b/app/models/workgroup.rb index 6c93d693..819c75bd 100644 --- a/app/models/workgroup.rb +++ b/app/models/workgroup.rb @@ -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 diff --git a/app/views/ordergroups/edit.html.haml b/app/views/ordergroups/edit.html.haml index 3a3eacba..7fec2484 100644 --- a/app/views/ordergroups/edit.html.haml +++ b/app/views/ordergroups/edit.html.haml @@ -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/ diff --git a/app/views/ordergroups/index.html.haml b/app/views/ordergroups/index.html.haml index a436cbe1..35c1b4ac 100644 --- a/app/views/ordergroups/index.html.haml +++ b/app/views/ordergroups/index.html.haml @@ -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 diff --git a/app/views/orders/_articles.html.haml b/app/views/orders/_articles.html.haml index 3f176128..8508e6e8 100644 --- a/app/views/orders/_articles.html.haml +++ b/app/views/orders/_articles.html.haml @@ -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' diff --git a/app/views/shared/_group.html.haml b/app/views/shared/_group.html.haml index eebe4cac..b9b914ce 100644 --- a/app/views/shared/_group.html.haml +++ b/app/views/shared/_group.html.haml @@ -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') diff --git a/app/views/shared/_group_form_fields.html.haml b/app/views/shared/_group_form_fields.html.haml index f13b0054..44376eaf 100644 --- a/app/views/shared/_group_form_fields.html.haml +++ b/app/views/shared/_group_form_fields.html.haml @@ -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 } diff --git a/app/views/stockit/history.haml b/app/views/stockit/history.haml new file mode 100644 index 00000000..f4fe2b07 --- /dev/null +++ b/app/views/stockit/history.haml @@ -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] diff --git a/app/views/stockit/index.html.haml b/app/views/stockit/index.html.haml index 777bb4b1..4673b967 100644 --- a/app/views/stockit/index.html.haml +++ b/app/views/stockit/index.html.haml @@ -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 diff --git a/app/views/tasks/_form.html.haml b/app/views/tasks/_form.html.haml index 3878f89f..95f3b134 100644 --- a/app/views/tasks/_form.html.haml +++ b/app/views/tasks/_form.html.haml @@ -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 diff --git a/app/views/tasks/_list.haml b/app/views/tasks/_list.haml index a0b2af22..da91cec8 100644 --- a/app/views/tasks/_list.haml +++ b/app/views/tasks/_list.haml @@ -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 diff --git a/app/views/tasks/show.haml b/app/views/tasks/show.haml index 23b843c7..8777d15d 100644 --- a/app/views/tasks/show.haml +++ b/app/views/tasks/show.haml @@ -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' diff --git a/app/views/tasks/workgroup.haml b/app/views/tasks/workgroup.haml index a5525d90..b9f81b7f 100644 --- a/app/views/tasks/workgroup.haml +++ b/app/views/tasks/workgroup.haml @@ -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 diff --git a/app/views/workgroups/edit.html.haml b/app/views/workgroups/edit.html.haml index 9346430a..896c8a91 100644 --- a/app/views/workgroups/edit.html.haml +++ b/app/views/workgroups/edit.html.haml @@ -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/ diff --git a/app/views/workgroups/index.html.haml b/app/views/workgroups/index.html.haml index ab1ca879..ed688695 100644 --- a/app/views/workgroups/index.html.haml +++ b/app/views/workgroups/index.html.haml @@ -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 diff --git a/config/initializers/extensions.rb b/config/initializers/extensions.rb index a6577545..1f71d542 100644 --- a/config/initializers/extensions.rb +++ b/config/initializers/extensions.rb @@ -9,4 +9,11 @@ class String string end end -end \ No newline at end of file +end + +class Array + def cumulative_sum + csum = 0 + self.map{|val| csum += val} + end +end diff --git a/config/locales/de.yml b/config/locales/de.yml index fe3cf387..200cd086 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -83,6 +83,11 @@ de: too_long: ist zu lang (nicht mehr als %{count} Zeichen) too_short: ist zu kurz (nicht weniger als %{count} Zeichen) wrong_length: hat die falsche Länge (muss genau %{count} Zeichen haben) + models: + task: + attributes: + done: + exclusion: erledigte Aufgaben können nicht wöchentlich wiederholt werden template: body: ! 'Bitte überprüfen Sie die folgenden Felder:' header: @@ -1443,7 +1448,7 @@ de: sessions: logged_in: Angemeldet! logged_out: Abgemeldet! - login_invalid: + login_invalid: Ungültiger Benutzername oder Passwort new: forgot_password: Passwort vergessen? login: Anmelden @@ -1650,12 +1655,6 @@ de: role_finance: Finanzen role_orders: Bestellverwaltung role_suppliers: Lieferanten - task_description: Beschreibung - task_duration: Vor. Dauer in Stunden - task_name: Name für Job - task_required_users: Benötige Verantwortliche - weekday: Wochentag - weekly_task: Monatlichen Job definieren? 'no': Nein required: mark: ! '*' @@ -1701,6 +1700,15 @@ de: title: Lagerartikel bearbeiten form: price_hint: Um Chaos zu vermeiden können bis auf weiteres die Preise von angelegten Lagerartikeln nicht mehr verändert werden. + history: + change_quantity: Veränderung + datetime: Zeitpunkt + delivery: Lieferung + new_quantity: Neuer Bestand + order: Bestellung + reason: Ereignis + stock_changes: Verlauf anzeigen für »%{article_name}« + stock_taking: Inventur index: article: article: Artikel @@ -1780,12 +1788,15 @@ de: notice: Aufgabe wurde gelöscht edit: title: Aufgabe bearbeiten + warning_periodic: Warnung: Diese Aufgabe ist Teil einer Gruppe von wöchentlichen Aufgaben. Beim Speichern wird sie aus der Gruppe ausgeschlossen und in eine gewöhnliche Aufgabe umgewandelt. error_not_found: Keine Arbeitsgruppe gefunden form: search: hint: Nach Nutzerin suchen noresult: Keine Nutzerin gefunden placeholder: Suche ... + submit: + periodic: Wöchentliche Aufgabe speichern index: show_group_tasks: Gruppenaufgaben anzeigen title: Aufgaben @@ -1809,10 +1820,13 @@ de: new_task: Neue Aufgabe erstellen new: title: Neue Aufgabe erstellen + repeated: Aufgabe wird wöchentlich wiederholt set_done: notice: Aufgabenstatus wurde aktualisiert show: accept_task: Aufgabe übernehmen + confirm_delete_group: Diese und alle folgenden wöchentlichen Aufgaben wirklich löschen? + delete_group: Aufgabe und folgende löschen due_date: Fälligkeitsdatum hours: ! '%{count}h' mark_done: Als erledigt markieren @@ -1820,6 +1834,7 @@ de: title: Aufgabe anzeigen update: notice: Aufgabe wurde aktualisiert + notice_converted: Aufgabe wurde aktualisiert und in eine gewöhnliche Aufgabe umgewandelt user: more: Nichts zu tun? %{tasks_link} gibt es bestimmt Arbeit tasks_link: Hier @@ -1829,11 +1844,6 @@ de: workgroup: title: Aufgaben für %{workgroup} title_all: Alle Aufgaben der Gruppe - weekly: - desc: ! '

Jeden %{weekday} hat diese Arbeitsgruppe folgenden Job: %{task}

Die Wochenaufgaben werden von der Foodsoft automatisch erstellt. Eintragen müsst Ihr Euch aber selber.

' - edit: Wöchentliche Aufgaben anpassen - empty: Noch keine Wochenaufgaben angelegt. - title: Wöchentliche Aufgaben time: am: vormittags formats: @@ -1845,6 +1855,7 @@ de: close: Schließen delete: Löschen edit: Bearbeiten + history: Verlauf anzeigen marks: close: ! '×' success: ! '' diff --git a/config/locales/en.yml b/config/locales/en.yml index c43f47ce..1d68511a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -83,6 +83,11 @@ en: too_long: is too long (no more than %{count} characters) too_short: is too short (use more than %{count} characters) wrong_length: is the wrong length (has to have exactly %{count} characters) + models: + task: + attributes: + done: + exclusion: finished tasks may not be repeated weekly template: body: ! 'Please check the following fields:' header: @@ -1652,12 +1657,6 @@ en: role_finance: Finances role_orders: Order management role_suppliers: Suppliers - task_description: Description - task_duration: Duration in hours - task_name: Task name - task_required_users: People required - weekday: Weekday - weekly_task: Define monthly task? 'no': 'No' required: mark: ! '*' @@ -1703,6 +1702,15 @@ en: title: Edit stock articles form: price_hint: To avoid choas, it is not possible to edit the prices of already added stock articles until further notice. + history: + change_quantity: Change + datetime: Time + delivery: Delivery + new_quantity: New quantity + order: Order + reason: Reason + stock_changes: Stock quantity changes of ‘%{article_name}’ + stock_taking: Inventory index: article: article: Article @@ -1782,12 +1790,15 @@ en: notice: Task has been deleted edit: title: Edit task + warning_periodic: Warning: This task is part of a group of weekly tasks. When saving it will be excluded from the group and it will be converted to a regular task. error_not_found: No workgroup found form: search: hint: Search for user noresult: No user found placeholder: Search ... + submit: + periodic: Save weekly task index: show_group_tasks: Show group tasks title: Tasks @@ -1811,10 +1822,13 @@ en: new_task: Create new task new: title: Create new tasks + repeated: Task is repeated weekly set_done: notice: The state of the task has been updated show: accept_task: Accept task + confirm_delete_group: Really delete this and all subsequent tasks? + delete_group: Delete task and subsequent due_date: Due date hours: ! '%{count}h' mark_done: Mark task as done @@ -1822,6 +1836,7 @@ en: title: Show task update: notice: Task has been updated + notice_converted: Task has been updated and was converted to a regular task user: more: Nothing to do? %{tasks_link} are tasks for sure. tasks_link: Here @@ -1831,11 +1846,6 @@ en: workgroup: title: Tasks for %{workgroup} title_all: All group tasks - weekly: - desc: ! '

Every %{weekday} this workgroup has the following job: %{task}

The weektask has been created by Foodsoft automatically. You still have to sign up for it yourself.

' - edit: Edit weekly tasks - empty: No weekly tasks created yet. - title: Weekly tasks time: am: morning formats: @@ -1847,6 +1857,7 @@ en: close: Close delete: Delete edit: Edit + history: Show history marks: close: ! '×' or_cancel: or cancel diff --git a/config/locales/nl.yml b/config/locales/nl.yml index d059f462..64e54f15 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -81,6 +81,11 @@ nl: too_long: is te lang (niet meer dan %{count} tekens) too_short: is te kort (niet minder dan %{count} tekens) wrong_length: heeft de verkeerde lengte (moet precies %{count} tekens zijn) + models: + task: + attributes: + done: + exclusion: template: body: ! 'Controleer de volgende velden:' header: @@ -265,10 +270,10 @@ nl: edit_all_table: available_desc: beschikbaar available_short: besch. - order_number_desc: bestelnummer - order_number_short: best.nr. - price_desc: netto prijs - price_short: prijs + order_number_desc: Bestelnummer + order_number_short: Best.nr. + price_desc: Netto prijs + price_short: Prijs unit_quantity_desc: Groothandelsverpakkingsgrootte unit_quantity_short: Gr.Eenh. form: @@ -542,7 +547,7 @@ nl: total_fc: Som (FC-prijs) units: Eenheden index: - title: Gesloten orders + title: Gesloten bestellingen invoice: edit: Factuur bewerken invoice_amount: ! 'Factuurbedrag:' @@ -573,8 +578,8 @@ nl: orders: clear: afrekenen cleared: afgerekend (%{amount}) - close: direct afsluiten - confirm: Weet je zeker dat de je bestelling wilt afsluiten? + close: direct afrekenen + confirm: Weet je zeker dat de je bestelling wilt afrekenen? end: Einde ended: gesloten last_edited_by: Laatst aangepast door @@ -1092,7 +1097,7 @@ nl: number: currency: format: - delimiter: ! ',' + delimiter: ! ' ' format: ! '%n %u' precision: 2 separator: ! ',' @@ -1425,7 +1430,7 @@ nl: description: Omschrijving email: Email note: Notitie - order_number: Order nummer + order_number: Bestelnummer ordergroup: Huishouden password: Wachtwoord password_confirmation: Wachtwoord herhalen @@ -1450,7 +1455,7 @@ nl: note: Notitie number: Nummer order: Bestelling - paid_on: Betaalt op + paid_on: Betaald op supplier: Leverancier message: body: @@ -1513,16 +1518,10 @@ nl: workgroup: next_weekly_tasks_number: role_admin: - role_article_meta: - role_finance: + role_article_meta: Artikelbestand + role_finance: Financiën role_orders: - role_suppliers: - task_description: - task_duration: - task_name: - task_required_users: - weekday: - weekly_task: + role_suppliers: Leveranciers 'no': Nee required: mark: ! '*' @@ -1568,6 +1567,15 @@ nl: title: form: price_hint: + history: + change_quantity: + datetime: + delivery: + new_quantity: + order: + reason: + stock_changes: + stock_taking: index: article: article: @@ -1647,12 +1655,15 @@ nl: notice: edit: title: + warning_periodic: error_not_found: form: search: hint: noresult: placeholder: + submit: + periodic: index: show_group_tasks: title: @@ -1676,10 +1687,13 @@ nl: new_task: new: title: + repeated: set_done: notice: show: accept_task: + confirm_delete_group: + delete_group: due_date: hours: mark_done: @@ -1687,6 +1701,7 @@ nl: title: update: notice: + notice_converted: user: more: tasks_link: @@ -1696,11 +1711,6 @@ nl: workgroup: title: title_all: - weekly: - desc: - edit: - empty: - title: time: am: morgen formats: @@ -1712,6 +1722,7 @@ nl: close: Sluiten delete: Verwijder edit: Bewerk + history: marks: close: ! '×' or_cancel: of annuleren diff --git a/config/routes.rb b/config/routes.rb index 0cd59fde..d996881c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -96,6 +96,8 @@ Foodsoft::Application.routes.draw do get :articles_search get :fill_new_stock_article_form end + + get :history end resources :suppliers do diff --git a/db/migrate/20130615073715_create_periodic_task_groups.rb b/db/migrate/20130615073715_create_periodic_task_groups.rb new file mode 100644 index 00000000..87cf560b --- /dev/null +++ b/db/migrate/20130615073715_create_periodic_task_groups.rb @@ -0,0 +1,13 @@ +class CreatePeriodicTaskGroups < ActiveRecord::Migration + def change + create_table :periodic_task_groups do |t| + t.date :next_task_date + + t.timestamps + end + + change_table :tasks do |t| + t.references :periodic_task_group + end + end +end diff --git a/db/migrate/20130622095040_move_weekly_tasks.rb b/db/migrate/20130622095040_move_weekly_tasks.rb new file mode 100644 index 00000000..be316c5c --- /dev/null +++ b/db/migrate/20130622095040_move_weekly_tasks.rb @@ -0,0 +1,60 @@ +class MoveWeeklyTasks < ActiveRecord::Migration + def up + Workgroup.where(weekly_task: true).each do |workgroup| + task_group = PeriodicTaskGroup.create + puts "Moving weekly task for workgroup #{workgroup.name} to group #{task_group.id}" + workgroup.tasks.undone.each do |task| + task.update_column(:periodic_task_group_id, task_group.id) if weekly_task?(workgroup, task) + end + tasks = task_group.tasks.order(:due_date) + task_group.next_task_date = tasks.last.due_date + PeriodicTaskGroup::PeriodDays unless tasks.empty? + task_group.save! + puts "Associated #{tasks.count} tasks with group and set next_task_date to #{task_group.next_task_date}" + end + end + + def down + PeriodicTaskGroup.all.each do |task_group| + unless task_group.tasks.empty? + task = task_group.tasks.first + workgroup = task.workgroup + puts "Writing task data of group #{task_group.id} to workgroup #{workgroup.name}" + workgroup_attributes = { + weekly_task: true, + weekday: task.due_date.days_to_week_start(:sunday), + task_name: task.name, + task_description: task.description, + task_required_users: task.required_users, + task_duration: task.duration + } + workgroup.update_attributes workgroup_attributes + task_group.tasks.update_all weekly: true + end + end + end + +private + def weekly_task?(workgroup, task) + group_task = { + weekday: workgroup.weekday, + name: workgroup.task_name, + description: workgroup.task_description, + required_users: workgroup.task_required_users, + duration: workgroup.task_duration, + weekly: true, + done: false, + workgroup_id: workgroup.id + } + task_task = { + weekday: task.due_date.days_to_week_start(:sunday), + name: task.name, + description: task.description, + required_users: task.required_users, + duration: task.duration, + weekly: task.weekly, + done: task.done, + workgroup_id: task.workgroup_id + } + group_task == task_task + end +end diff --git a/db/migrate/20130624084223_remove_weekly_from_tasks.rb b/db/migrate/20130624084223_remove_weekly_from_tasks.rb new file mode 100644 index 00000000..4fefcb5b --- /dev/null +++ b/db/migrate/20130624084223_remove_weekly_from_tasks.rb @@ -0,0 +1,9 @@ +class RemoveWeeklyFromTasks < ActiveRecord::Migration + def up + remove_column :tasks, :weekly + end + + def down + add_column :tasks, :weekly, :boolean + end +end diff --git a/db/migrate/20130624085246_remove_weekly_task_from_groups.rb b/db/migrate/20130624085246_remove_weekly_task_from_groups.rb new file mode 100644 index 00000000..665651d9 --- /dev/null +++ b/db/migrate/20130624085246_remove_weekly_task_from_groups.rb @@ -0,0 +1,19 @@ +class RemoveWeeklyTaskFromGroups < ActiveRecord::Migration + def up + remove_column :groups, :weekly_task + remove_column :groups, :weekday + remove_column :groups, :task_name + remove_column :groups, :task_description + remove_column :groups, :task_required_users + remove_column :groups, :task_duration + end + + def down + add_column :groups, :task_duration, :integer + add_column :groups, :task_required_users, :integer + add_column :groups, :task_description, :string + add_column :groups, :task_name, :string + add_column :groups, :weekday, :integer + add_column :groups, :weekly_task, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index 188ea83b..d2a0dc72 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20121230142516) do +ActiveRecord::Schema.define(:version => 20130624085246) do create_table "article_categories", :force => true do |t| t.string "name", :default => "", :null => false @@ -143,17 +143,11 @@ ActiveRecord::Schema.define(:version => 20121230142516) do t.boolean "role_article_meta", :default => false, :null => false t.boolean "role_finance", :default => false, :null => false t.boolean "role_orders", :default => false, :null => false - t.boolean "weekly_task", :default => false - t.integer "weekday" - t.string "task_name" - t.string "task_description" - t.integer "task_required_users", :default => 1 t.datetime "deleted_at" t.string "contact_person" t.string "contact_phone" t.string "contact_address" t.text "stats" - t.integer "task_duration", :default => 1 t.integer "next_weekly_tasks_number", :default => 8 t.boolean "ignore_apple_restriction", :default => false end @@ -268,6 +262,12 @@ ActiveRecord::Schema.define(:version => 20121230142516) do add_index "pages", ["permalink"], :name => "index_pages_on_permalink" add_index "pages", ["title"], :name => "index_pages_on_title" + create_table "periodic_task_groups", :force => true do |t| + t.date "next_task_date" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "stock_changes", :force => true do |t| t.integer "delivery_id" t.integer "order_id" @@ -308,16 +308,16 @@ ActiveRecord::Schema.define(:version => 20121230142516) do add_index "suppliers", ["name"], :name => "index_suppliers_on_name", :unique => true create_table "tasks", :force => true do |t| - t.string "name", :default => "", :null => false + t.string "name", :default => "", :null => false t.string "description" t.date "due_date" - t.boolean "done", :default => false + t.boolean "done", :default => false t.integer "workgroup_id" - t.datetime "created_on", :null => false - t.datetime "updated_on", :null => false - t.integer "required_users", :default => 1 - t.boolean "weekly" - t.integer "duration", :default => 1 + t.datetime "created_on", :null => false + t.datetime "updated_on", :null => false + t.integer "required_users", :default => 1 + t.integer "duration", :default => 1 + t.integer "periodic_task_group_id" end add_index "tasks", ["due_date"], :name => "index_tasks_on_due_date" diff --git a/lib/tasks/foodsoft.rake b/lib/tasks/foodsoft.rake index fd96cf9c..3f042e65 100644 --- a/lib/tasks/foodsoft.rake +++ b/lib/tasks/foodsoft.rake @@ -16,21 +16,6 @@ namespace :foodsoft do end end - desc "Create upcoming workgroups tasks (next 3 to 7 weeks)" - task :create_upcoming_weekly_tasks => :environment do - workgroups = Workgroup.where(weekly_task: true) - for workgroup in workgroups - puts "Create weekly tasks for #{workgroup.name}" - # Loop through next tasks weekly tasks method, - # skip the next 3 weeks, to allow manually deleting tasks - workgroup.next_weekly_tasks[3..-1].each do |date| - unless workgroup.tasks.exists?({:due_date => date, :weekly => true}) - workgroup.tasks.create(workgroup.task_attributes(date)) - end - end - end - end - desc "Notify workgroup of upcoming weekly task" task :notify_users_of_weekly_task => :environment do for workgroup in Workgroup.all @@ -50,4 +35,15 @@ namespace :foodsoft do end end end + + desc "Create upcoming periodic tasks" + task :create_upcoming_periodic_tasks => :environment do + for tg in PeriodicTaskGroup.all + if tg.has_next_task? + while tg.next_task_date.nil? or tg.next_task_date < Date.today + 50 + tg.create_next_task + end + end + end + end end