OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/app/models/cost_query/operator.rb

247 lines
5.6 KiB

class CostQuery::Operator
include CostQuery::QueryUtils
#############################################################################################
# Wrapped so we can place this at the top of the file.
def self.define_operators # :nodoc:
# Defaults
defaults do
def sql_operator
name
end
def where_clause
"%s %s '%s'"
end
def modify(query, field, *values)
query.where [where_clause, field, sql_operator, *values]
query
end
def label
@label ||= Query.operators[name]
end
end
# Operators from Redmine
new ">t-" do
include DateRange
def modify(query, field, value)
super query, field, -value.to_i, 0
end
end
new "w" do
def modify(query, field, offset = nil)
offset ||= 0
from = Time.now.at_beginning_of_week - ((l(:general_first_day_of_week).to_i % 7) + 1).days
from -= offset.days
'<>d'.to_operator.modify query, field, from, from + 7.days
end
end
new "t+" do
include DateRange
def modify(query, field, *values)
super query, field, values.first.to_i, values.first.to_i
end
end
new "<="
new "!" do
def modify(query, field, *values)
query.where "(#{field} IS NULL OR #{field} NOT IN #{collection(*values)})"
query
end
end
new "t-" do
include DateRange
def modify(query, field, *values)
super query, field, -values.first.to_i, -values.first.to_i
end
end
new "c" do
def modify(query, field, *values)
raise "wrong field" if field.to_s.split('.').last != "status_id"
"=".to_operator.modify(query, "#{IssueStatus.table_name}.is_closed", quoted_true)
end
end
new "o" do
def modify(query, field, *values)
raise "wrong field" if field.to_s.split('.').last != "status_id"
"=".to_operator.modify(query, "#{IssueStatus.table_name}.is_closed", quoted_false)
end
end
new "!~" do
def modify(query, field, value)
query.where "LOWER(#{field}) NOT LIKE '%#{quote_string(value.to_s.downcase)}%'"
query
end
end
new "=" do
def modify(query, field, *values)
query.where "#{field} IN #{collection(*values)}"
query
end
end
new "~" do
def modify(query, field, value)
query.where "LOWER(#{field}) LIKE '%#{quote_string(value.to_s.downcase)}%'"
query
end
end
new "<t+" do
include DateRange
def modify(query, field, value)
super query, field, 0, value.to_i
end
end
new "t" do
include DateRange
def modify(query, field, value=nil)
super query, field, 0, 0
end
end
new ">=" # done
new "!*", :where_clause => "%s IS NULL"
new "<t-" do
include DateRange
def modify(query, field, value)
super query, field, nil, -value.to_i
end
end
new ">t+" do
include DateRange
def modify(query, field, value)
super query, field, value.to_i, nil
end
end
new "*", :where_clause => "%s IS NOT NULL"
# Our own operators
new "<", :label => :label_less
new ">", :label => :label_greater
new "=n", :label => :label_equals do
def modify(query, field, value)
query.where "#{field} = #{clean_currency(value)}"
query
end
end
new "0", :label => :label_none, :where_clause => "%s = 0"
new "y", :label => :label_yes, :where_clause => "%s IS NOT NULL"
new "n", :label => :label_no, :where_clause => "%s IS NULL"
new "<d", :label => :label_less_or_equal do
def modify(query, field, value)
"<".to_operator.modify query, field, quoted_date(value)
end
end
new ">d", :label => :label_greater_or_equal do
def modify(query, field, value)
">".to_operator.modify query, field, quoted_date(value)
end
end
new "<>d", :label => :label_between do
def modify(query, field, from, to)
query.where "#{field} BETWEEN '#{quoted_date from}' AND '#{quoted_date to}'"
query
end
end
new "=d", :label => :label_date_on do
def modify(query, field, value)
"=".to_operator.modify query, field, quoted_date(value)
end
end
end
#############################################################################################
module CoreExt
::String.send :include, self
::Symbol.send :include, self
def to_operator
CostQuery::Operator.find self
end
end
def self.new(name, values = {}, &block)
all[name.to_s] ||= super
end
def self.all
@all ||= {}
end
def self.load
return if @done
@done = true
define_operators
end
def self.find(name)
all[name.to_s] or raise ArgumentError, "Operator not defined"
end
def self.defaults(&block)
class_eval &block
end
def self.default_operator
find "="
end
attr_reader :name
def initialize(name, values = {}, &block)
@name = name.to_s
values.each do |key, value|
metaclass.class_eval { define_method(key) { value } }
end
metaclass.class_eval(&block) if block
end
def to_operator
self
end
def inspect
"#<#{self.class.name}:#{name.inspect}>"
end
def <=>(other)
self.name <=> other.name
end
module DateRange
def modify(query, field, from, to)
query.where ["#{field} > '%s'", quoted_date((Date.yesterday + from).to_time.end_of_day)] if from
query.where ["#{field} <= '%s'", quoted_date((Date.today + to).to_time.end_of_day)] if to
query
end
end
# Done with class method definition, let's initialize the operators
load
end