Chris@1295: # Redmine - project management software Chris@1295: # Copyright (C) 2006-2013 Jean-Philippe Lang Chris@1295: # Chris@1295: # This program is free software; you can redistribute it and/or Chris@1295: # modify it under the terms of the GNU General Public License Chris@1295: # as published by the Free Software Foundation; either version 2 Chris@1295: # of the License, or (at your option) any later version. Chris@1295: # Chris@1295: # This program is distributed in the hope that it will be useful, Chris@1295: # but WITHOUT ANY WARRANTY; without even the implied warranty of Chris@1295: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Chris@1295: # GNU General Public License for more details. Chris@1295: # Chris@1295: # You should have received a copy of the GNU General Public License Chris@1295: # along with this program; if not, write to the Free Software Chris@1295: # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Chris@1295: Chris@1295: class TimeEntryQuery < Query Chris@1295: Chris@1295: self.queried_class = TimeEntry Chris@1295: Chris@1295: self.available_columns = [ Chris@1295: QueryColumn.new(:project, :sortable => "#{Project.table_name}.name", :groupable => true), Chris@1295: QueryColumn.new(:spent_on, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"], :default_order => 'desc', :groupable => true), Chris@1295: QueryColumn.new(:user, :sortable => lambda {User.fields_for_order_statement}, :groupable => true), Chris@1295: QueryColumn.new(:activity, :sortable => "#{TimeEntryActivity.table_name}.position", :groupable => true), Chris@1295: QueryColumn.new(:issue, :sortable => "#{Issue.table_name}.id"), Chris@1295: QueryColumn.new(:comments), Chris@1295: QueryColumn.new(:hours, :sortable => "#{TimeEntry.table_name}.hours"), Chris@1295: ] Chris@1295: Chris@1295: def initialize(attributes=nil, *args) Chris@1295: super attributes Chris@1295: self.filters ||= {} Chris@1295: add_filter('spent_on', '*') unless filters.present? Chris@1295: end Chris@1295: Chris@1295: def initialize_available_filters Chris@1295: add_available_filter "spent_on", :type => :date_past Chris@1295: Chris@1295: principals = [] Chris@1295: if project Chris@1295: principals += project.principals.sort Chris@1295: unless project.leaf? Chris@1295: subprojects = project.descendants.visible.all Chris@1295: if subprojects.any? Chris@1295: add_available_filter "subproject_id", Chris@1295: :type => :list_subprojects, Chris@1295: :values => subprojects.collect{|s| [s.name, s.id.to_s] } Chris@1295: principals += Principal.member_of(subprojects) Chris@1295: end Chris@1295: end Chris@1295: else Chris@1295: if all_projects.any? Chris@1295: # members of visible projects Chris@1295: principals += Principal.member_of(all_projects) Chris@1295: # project filter Chris@1295: project_values = [] Chris@1295: if User.current.logged? && User.current.memberships.any? Chris@1295: project_values << ["<< #{l(:label_my_projects).downcase} >>", "mine"] Chris@1295: end Chris@1295: project_values += all_projects_values Chris@1295: add_available_filter("project_id", Chris@1295: :type => :list, :values => project_values Chris@1295: ) unless project_values.empty? Chris@1295: end Chris@1295: end Chris@1295: principals.uniq! Chris@1295: principals.sort! Chris@1295: users = principals.select {|p| p.is_a?(User)} Chris@1295: Chris@1295: users_values = [] Chris@1295: users_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? Chris@1295: users_values += users.collect{|s| [s.name, s.id.to_s] } Chris@1295: add_available_filter("user_id", Chris@1295: :type => :list_optional, :values => users_values Chris@1295: ) unless users_values.empty? Chris@1295: Chris@1295: activities = (project ? project.activities : TimeEntryActivity.shared.active) Chris@1295: add_available_filter("activity_id", Chris@1295: :type => :list, :values => activities.map {|a| [a.name, a.id.to_s]} Chris@1295: ) unless activities.empty? Chris@1295: Chris@1295: add_available_filter "comments", :type => :text Chris@1295: add_available_filter "hours", :type => :float Chris@1295: Chris@1295: add_custom_fields_filters(TimeEntryCustomField.where(:is_filter => true).all) Chris@1295: add_associations_custom_fields_filters :project, :issue, :user Chris@1295: end Chris@1295: Chris@1295: def available_columns Chris@1295: return @available_columns if @available_columns Chris@1295: @available_columns = self.class.available_columns.dup Chris@1295: @available_columns += TimeEntryCustomField.all.map {|cf| QueryCustomFieldColumn.new(cf) } Chris@1295: @available_columns += IssueCustomField.all.map {|cf| QueryAssociationCustomFieldColumn.new(:issue, cf) } Chris@1295: @available_columns Chris@1295: end Chris@1295: Chris@1295: def default_columns_names Chris@1295: @default_columns_names ||= [:project, :spent_on, :user, :activity, :issue, :comments, :hours] Chris@1295: end Chris@1295: Chris@1295: # Accepts :from/:to params as shortcut filters Chris@1295: def build_from_params(params) Chris@1295: super Chris@1295: if params[:from].present? && params[:to].present? Chris@1295: add_filter('spent_on', '><', [params[:from], params[:to]]) Chris@1295: elsif params[:from].present? Chris@1295: add_filter('spent_on', '>=', [params[:from]]) Chris@1295: elsif params[:to].present? Chris@1295: add_filter('spent_on', '<=', [params[:to]]) Chris@1295: end Chris@1295: self Chris@1295: end Chris@1295: end