diff --git a/app/controllers/periodictask_controller.rb b/app/controllers/periodictask_controller.rb index 3761ad1..aa09a05 100644 --- a/app/controllers/periodictask_controller.rb +++ b/app/controllers/periodictask_controller.rb @@ -4,6 +4,7 @@ class PeriodictaskController < ApplicationController class << self alias_method :before_action, :before_filter end unless respond_to?(:before_action) + before_action :find_project #before_filter :find_periodictask, :except => [:new, :create, :index] before_action :load_users, :except => [:destroy] @@ -73,7 +74,14 @@ def customfields @periodictask = params[:periodictask][:id].present? ? Periodictask.accessible.find(params[:periodictask][:id]) : Periodictask.new(:project=>@project, :author_id=>User.current.id) @periodictask.attributes = params[:periodictask] @issue = @periodictask.generate_issue + end + + def facility + @periodictask = params[:periodictask][:id].present? ? Periodictask.accessible.find(params[:periodictask][:id]) : Periodictask.new(:project=>@project, :author_id=>User.current.id) + @periodictask.attributes = params[:periodictask] end + + private diff --git a/app/models/periodictask.rb b/app/models/periodictask.rb index 8a1b4bf..aa26129 100644 --- a/app/models/periodictask.rb +++ b/app/models/periodictask.rb @@ -1,8 +1,12 @@ +require File.dirname(__FILE__) + '/../../../redmine_dit_kpi/lib/redmine_dit_kpi/acl' + class Periodictask < ActiveRecord::Base unloadable belongs_to :project belongs_to :assigned_to, :class_name => 'Principal', :foreign_key => 'assigned_to_id' belongs_to :issue_category, :class_name => 'IssueCategory', :foreign_key => 'issue_category_id' + belongs_to :issue_facility, :class_name => 'KpiFacility', :foreign_key => 'facility_id' + serialize :custom_field_values # adapted to changes concerning mass-assigning values to attributes #attr_accessible *column_names @@ -12,7 +16,7 @@ class Periodictask < ActiveRecord::Base after_initialize do |task| if task.new_record? task.interval_number ||= 1 - task.interval_units ||= INTERVAL_UNITS.first[1]; + task.interval_units ||= Periodictask.INTERVAL_UNITS.first[1]; end end @@ -27,37 +31,81 @@ class Periodictask < ActiveRecord::Base end } - INTERVAL_UNITS = [ - [l(:label_unit_day), 'day'], - [l(:label_unit_business_day), 'business_day'], - [l(:label_unit_week), 'week'], - [l(:label_unit_month), 'month'], - [l(:label_unit_year), 'year'] - ] - - def generate_issue(now = Time.now) - if project.try(:active?) - # Copy subject and description and replace variables - subj = parse_macro(subject.try(:dup), now) - desc = parse_macro(description.try(:dup), now) - - issue = Issue.new(:project_id => project_id, :tracker_id => tracker_id || project.trackers.first.try(:id), :category_id => issue_category_id, - :assigned_to_id => assigned_to_id, :author_id => author_id, - :subject => subj, :description => desc) - issue.start_date ||= now.to_date if set_start_date? - if due_date_number - due_date = due_date_number - due_date_units = due_date_units || 'day' - issue.due_date = due_date.send(due_date_units.downcase).from_now - end - issue.estimated_hours = estimated_hours + #** INTERVAL_UNITS + def self.INTERVAL_UNITS() + [ + [ l(:label_unit_day), 'day' ], + [ l(:label_unit_business_day ), 'business_day' ], + [ l(:label_unit_week), 'week' ], + [ l(:label_unit_month), 'month' ], + [ l(:label_unit_year), 'year' ] + ] + end + + #** trimTimeZone + def self.trimTimeZone( aDateTime ) + puts 'AAAAAAAAAAAAAAAAAAAA 0 ' + aDateTime.inspect + t = aDateTime.to_s.dup + t.delete_suffix!( ' UTC' ) + t.gsub!( / \+[0-8]+/, '' ) + puts 'AAAAAAAAAAAAAAAAAAAA 1 ' + t + return t + end - fill_checklists issue - fill_custom_fields issue + #** generate_issue + def generate_issue(now = Time.now) + return unless project.try( :active? ) + # puts "AAAAAAAAAAAAAAAAAAAAAAAAAA " + inspect + # Copy subject and description and replace variables + subj = parse_macro( subject.try( :dup ), now ) + desc = parse_macro( description.try( :dup ), now ) - issue + issue = Issue.new(:project_id => project_id, :tracker_id => tracker_id || project.trackers.first.try(:id), :category_id => issue_category_id, + :assigned_to_id => assigned_to_id, :author_id => author_id, + :subject => subj, :description => desc, :facility_id => facility_id ) + + issue.start_date ||= now.to_date if set_start_date? + if due_date_number + due_date = due_date_number + due_date_units = due_date_units || 'day' + issue.due_date = due_date.send(due_date_units.downcase).from_now + end + + issue.estimated_hours = estimated_hours + + fill_checklists issue + fill_custom_fields issue + + issue + end + + #** filterFacilityByTrackerId + def filterFacilityByTrackerId( aTrackerId ) + # puts "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL " + aTrackerId.to_s + acl.filterFacilityByTrackerId( aTrackerId ) + end + + # acl + def acl + RedmineDitKpi::Acl + end + + def copy(source_periodictask) + attributes = source_periodictask.attributes.dup.except('id', 'created_at', 'updated_at') + self.attributes = attributes + if !source_periodictask.custom_field_values.nil? + self.custom_field_values = source_periodictask.custom_field_values.inject({}) {|h, v| h[v.custom_field_id] = v.value; h} + end + self.checklists_template_id = source_periodictask.checklists_template_id + save + self + end + + def self.copy_from(source_periodictask) + new_task = self.new + new_task.copy(source_periodictask) + new_task end - end private def parse_macro(str, now) @@ -91,4 +139,6 @@ def fill_checklists(issue) def fill_custom_fields(issue) issue.custom_field_values = custom_field_values.to_unsafe_hash if custom_field_values.respond_to?(:to_unsafe_hash) end + + end diff --git a/app/views/periodictask/_facility.html.erb b/app/views/periodictask/_facility.html.erb new file mode 100644 index 0000000..8c76303 --- /dev/null +++ b/app/views/periodictask/_facility.html.erb @@ -0,0 +1 @@ +
<%= label(:periodictask, :facility_id, l(:label_facility)) %><%= collection_select( 'periodictask', 'facility_id', @periodictask.filterFacilityByTrackerId( 0 ), :id, :name ) %>
\ No newline at end of file diff --git a/app/views/periodictask/_form.html.erb b/app/views/periodictask/_form.html.erb index c6986a0..71e5362 100644 --- a/app/views/periodictask/_form.html.erb +++ b/app/views/periodictask/_form.html.erb @@ -29,17 +29,18 @@ <% end %><%= label(:periodictask, :interval_number, l(:label_interval)) %><%= f.number_field :interval_number, :required => true, :min => 1 %> - <%= select 'periodictask', 'interval_units', Periodictask::INTERVAL_UNITS %>
+ <%= select 'periodictask', 'interval_units', Periodictask.INTERVAL_UNITS %><%= label(:periodictask, :tracker_id, l(:label_tracker)) %><%= collection_select("periodictask", "tracker_id", @project.trackers, :id, :name ) %>
+ <%= render :partial => 'facility', :locals => { :issue => @issue } %><%= label(:periodictask, :set_start_date, l(:label_set_start_date)) %><%= f.check_box :set_start_date %>
-<%= label(:periodictask, :due_date, l(:label_due_date)) %><%= f.text_field :due_date_number, :size => 3 %><%= select 'periodictask', 'due_date_units', Periodictask::INTERVAL_UNITS %>
+<%= label(:periodictask, :due_date, l(:label_due_date)) %><%= f.text_field :due_date_number, :size => 3 %><%= select 'periodictask', 'due_date_units', Periodictask.INTERVAL_UNITS %>
<%= label(:periodictask, :estimated_hours, l(:label_estimated_hours)) %><%= f.number_field :estimated_hours, step: :any %> <%= l(:label_estimated_hours_after) %>
-<%= label(:periodictask, :next_run_date, l(:label_next_run_date)) %><%= f.text_field :next_run_date %>
+<%= label(:periodictask, :next_run_date, l(:label_next_run_date)) %><%= text_field_tag 'periodictask[next_run_date]', Periodictask.trimTimeZone( @periodictask.next_run_date ) %>
<%= label(:periodictask, :description, l(:label_description)) %><%= f.text_area :description, :cols => 100, :rows => 10, :no_label => true %>
<% if checklistPluginInstalled? %><%= label(:periodictask, :checklists_template_id, l(:label_checklist_template)) %> - <%= select :periodictask, :checklists_template_id, template_options_for_select(@project, f.object.checklists_template_id) %> + <%= select :periodictask, :checklists_template_id, template_options_for_select(@project, f.object.checklists_template_id) %>
<% end %> <% if @periodictask.last_error.present? %> @@ -55,13 +56,29 @@ <%= javascript_tag do %> - $(document).ready(function() { +$(document).ready(function() { $('#periodictask_tracker_id').change(function() { - $.ajax({ - url: '<%= escape_javascript(periodictask_customfields_path(@project, :format => 'js')) %>', - type: 'post', - data: $(this).closest('form').serialize() - }); + data = $(this).closest('form').serialize(); + + $.ajax({ + url: '<%= escape_javascript(periodictask_customfields_path(@project, :format => 'js')) %>', + type: 'post', + data: data + }); + + updateFacility(); }); - }); + + function updateFacility() { + // $.get( 'facility', data, 'script' ); + data = $('#periodictask_tracker_id').closest('form').serialize(); + $.ajax({ + url: '<%= escape_javascript(periodictask_facility_path(@project, :format => 'js')) %>', + type: 'post', + data: data + }); + } + + updateFacility(); +}); <% end %> diff --git a/app/views/periodictask/facility.js.erb b/app/views/periodictask/facility.js.erb new file mode 100644 index 0000000..b91f7a2 --- /dev/null +++ b/app/views/periodictask/facility.js.erb @@ -0,0 +1 @@ +$( '#periodictask_facility_id' ).html( '<%= puts 'KKKKKKKKK' + @periodictask.inspect; escape_javascript options_from_collection_for_select( @periodictask.filterFacilityByTrackerId( @periodictask.tracker_id ), :id, :name, @periodictask.facility_id ) %>' ); diff --git a/app/views/periodictask/index.html.erb b/app/views/periodictask/index.html.erb index 031ddc6..24aa2be 100644 --- a/app/views/periodictask/index.html.erb +++ b/app/views/periodictask/index.html.erb @@ -1,17 +1,27 @@ <% if @project_identifier %> + +<%= l(:label_scheduled_tasks) %>
-| <%= l(:label_subject) %> | <%= l(:label_issue_category) %> | <%= l(:label_next_run_date) %> |   | + | <%= l(:label_subject) %> | <%= l(:label_issue_facility) %> | <%= l(:label_next_run_date) %> | <%= l(:label_interval) %> |   | <%= a.issue_category%> | -<%= a.next_run_date %> | +<%= a.issue_facility%> | +<%= Periodictask.trimTimeZone( a.next_run_date ) %> | +<%= a.interval_number %>/<%= l( "label_unit_" + a.interval_units ) %> | <%= link_to l(:button_edit), {:controller => 'periodictask', :action => 'edit', :id => a.id, :project_id => @project}, diff --git a/config/locales/en.yml b/config/locales/en.yml index 1944df6..f5cb70c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,6 +1,7 @@ # English strings go here for Rails i18n en: label_tracker: Tracker + label_facility: Facility label_author: Author label_assigned_to_user: Assigned to user no_members_in_project: This project has no members @@ -34,3 +35,6 @@ en: subject_variables: Possible variables are **DAY** (01-31), **WEEK** (01-53), **MONTH** (01-12), **MONTHNAME** and **PREVIOUS_MONTHNAME** (January - December), **YEAR** (YYYY) label_last_error: Last error label_issue_custom_fields: Issue custom fields + menu_periodic_tasks: Periodic Tasks + permission_periodictask: Edit periodic tasks + project_module_periodictask: Periodic tasks diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 8aaedd6..3454388 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -8,15 +8,15 @@ ru: label_subject: Тема label_next_run_date: Дата следующего запуска (yyyy-mm-dd hh:mm:ss) label_edit_periodic_task: Редактировать периодическую задачу - label_new_periodic_task: Новая периодическая задача + label_new_periodic_task: Новая периодическая/плановая задача label_no_members_in_project: В этом проекте нет участников label_no_categories_in_project: В этом проекте нет категорий - label_periodic_tasks: Периодические Задачи + label_periodic_tasks: Периодические/плановые Задачи label_create_periodic_task: Создать label_save_periodic_task: Сохранить label_scheduled_tasks: Запланированные задачи label_no_project: ID проекта не указан - label_remove_periodic_task: Удалить периодическую задачу + label_remove_periodic_task: Удалить периодическую/плановую задачу label_interval: Интервал label_set_start_date: Установить дату начала label_due_date: Плановая дата через @@ -25,10 +25,15 @@ ru: label_description: Описание label_issue_category: Категория задачи label_unit_day: дней - label_unit_business_day: рабочие дни + label_unit_business_day: раб. день (пн.-пт.) label_unit_week: неделя label_unit_month: месяц label_unit_year: год(лет) - flash_task_created: Периодическа задача создана - flash_task_saved: Периодическа задача сохранена - subject_variables: Возможные переменные **DAY** (01-31), **WEEK** (01-53), **MONTH** (01-12), **MONTHNAME** и **PREVIOUS_MONTHNAME** (января - декабря), **PREVIOUS_MONTHNAME** передыдущий месяц, **YEAR** (YYYY) + flash_task_created: Периодическая задача создана + flash_task_saved: Периодическая задача сохранена + subject_variables: Доступны переменные **DAY** (01-31), **WEEK** (01-53), **MONTH** (01-12), **MONTHNAME** и **PREVIOUS_MONTHNAME** (января - декабря), **PREVIOUS_MONTHNAME** передыдущий месяц, **YEAR** (YYYY) + menu_periodic_tasks: Плановые задачи + permission_periodictask: Редактировать плановые задачи + project_module_periodictask: Плановые задачи + label_facility: Услуга + label_issue_facility: Услуга \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 98df77f..875f8f6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,6 +4,8 @@ # and the new verb 'patch' for compatibility with Redmine 3 and below match 'projects/:project_id/periodictask/customfields', :to => 'periodictask#customfields', :as => 'periodictask_customfields', :via => [:post, :patch] + match 'projects/:project_id/periodictask/facility', :to => 'periodictask#facility', :as => 'periodictask_facility', :via => [:post, :patch] + get 'projects/:project_id/periodictask', :to => 'periodictask#index', :as => 'periodictasks' get 'projects/:project_id/periodictask/new', :to => 'periodictask#new', :as => 'new_periodictask' post 'projects/:project_id/periodictask', :to => 'periodictask#create' diff --git a/db/migrate/20200921141400_add_facility_id_to_periodictasks.rb b/db/migrate/20200921141400_add_facility_id_to_periodictasks.rb new file mode 100644 index 0000000..8581f8a --- /dev/null +++ b/db/migrate/20200921141400_add_facility_id_to_periodictasks.rb @@ -0,0 +1,11 @@ +active_record_migration_class = ActiveRecord::Migration.respond_to?(:current_version) ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration + +class AddFacilityIdToPeriodictasks < active_record_migration_class + def self.up + add_column :periodictasks, :facility_id, :integer, :default => 0, :null => false, comment: 'Услуга' + end + + def self.down + remove_column :periodictasks, :facility_id + end +end diff --git a/init.rb b/init.rb index 1fefad3..bfde51f 100644 --- a/init.rb +++ b/init.rb @@ -18,5 +18,5 @@ permission :periodictask, {:periodictask => [:index, :edit]} end - menu :project_menu, :periodictask, { :controller => 'periodictask', :action => 'index' }, :caption => 'Periodic Task', :after => :settings, :param => :project_id + menu :project_menu, :periodictask, { :controller => 'periodictask', :action => 'index' }, :caption => :menu_periodic_tasks, :after => :settings, :param => :project_id end diff --git a/lib/scheduled_tasks_checker.rb b/lib/scheduled_tasks_checker.rb index 492208c..7358a3d 100644 --- a/lib/scheduled_tasks_checker.rb +++ b/lib/scheduled_tasks_checker.rb @@ -1,34 +1,50 @@ class ScheduledTasksChecker - def self.checktasks! - now = Time.now - Periodictask.where("next_run_date <= ? ", now).each do |task| + def self.checktasks! + I18n.locale = ENV[ 'LOCALE' ] || I18n.default_locale + puts Periodictask.INTERVAL_UNITS.inspect; + + now = Time.now + Periodictask.where( "next_run_date <= ? ", now ).each do |task| - # replace variables (set locale from shell) - I18n.locale = ENV['LOCALE'] || I18n.default_locale - - issue = task.generate_issue(now) - if issue - begin - issue.save! - task.last_error = nil - rescue ActiveRecord::RecordInvalid => e - Rails.logger.error "ScheduledTasksChecker: #{e.message}" - task.last_error = e.message - end - interval = task.interval_number - units = task.interval_units.downcase - if units == "business_day" - task.next_run_date = task.interval_number.business_day.after(now) - else - interval_steps = ((now - task.next_run_date) / interval.send(units)).ceil - task.next_run_date += (interval * interval_steps).send(units) + # replace variables (set locale from shell) + I18n.locale = ENV[ 'LOCALE' ] || I18n.default_locale + + issue = task.generate_issue( now ) + if issue + begin + issue.save! + task.last_error = nil + rescue ActiveRecord::RecordInvalid => e + Rails.logger.error "ScheduledTasksChecker: #{e.message}" + task.last_error = e.message + end + + interval = task.interval_number + units = task.interval_units.downcase + #puts task.inspect + + if units == "business_day" + + # puts "AA 1 " + BusinessTime::Config.default_config.inspect + c = BusinessTime::Config.default_config.clone + + BusinessTime::Config.beginning_of_workday = Time.parse( '0:0:0' ) + BusinessTime::Config.end_of_workday = Time.parse( '23:59:0' ) + + task.next_run_date = task.interval_number.business_day.after( task.next_run_date ) + else + interval_steps = ( ( now - task.next_run_date ) / interval.send( units ) ).ceil + task.next_run_date += ( interval * interval_steps ).send( units ) + end + + puts 'NEXT RUN DATE: ' + task.next_run_date.inspect + else + msg = "Project is missing or closed" + Rails.logger.error "ScheduledTasksChecker: #{msg}" + task.last_error = msg + end + + task.save end - else - msg = "Project is missing or closed" - Rails.logger.error "ScheduledTasksChecker: #{msg}" - task.last_error = msg - end - task.save end - end end |
|---|