|
|
|
@ -21,14 +21,10 @@ class CostQuery::SqlStatement |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
include CostQuery::QueryUtils |
|
|
|
|
## |
|
|
|
|
# Describes the query. This may be used in a sql-comment later. |
|
|
|
|
attr_accessor :desc |
|
|
|
|
|
|
|
|
|
COMMON_FIELDS = %w[ |
|
|
|
|
user_id project_id issue_id rate_id |
|
|
|
|
comments spent_on created_on updated_on tyear tmonth tweek |
|
|
|
|
costs overridden_costs type |
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
## |
|
|
|
|
# Generates new SqlStatement. |
|
|
|
|
# |
|
|
|
@ -37,83 +33,6 @@ class CostQuery::SqlStatement |
|
|
|
|
from table |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
## |
|
|
|
|
# Generates SqlStatement that maps time_entries and cost_entries to a common structure. |
|
|
|
|
# |
|
|
|
|
# Mapping for direct fields: |
|
|
|
|
# |
|
|
|
|
# Result | Time Entires | Cost entries |
|
|
|
|
# --------------------------|--------------------------|-------------------------- |
|
|
|
|
# id | id | id |
|
|
|
|
# user_id | user_id | user_id |
|
|
|
|
# project_id | project_id | project_id |
|
|
|
|
# issue_id | issue_id | issue_id |
|
|
|
|
# rate_id | rate_id | rate_id |
|
|
|
|
# comments | comments | comments |
|
|
|
|
# spent_on | spent_on | spent_on |
|
|
|
|
# created_on | created_on | created_on |
|
|
|
|
# updated_on | updated_on | updated_on |
|
|
|
|
# tyear | tyear | tyear |
|
|
|
|
# tmonth | tmonth | tmonth |
|
|
|
|
# tweek | tweek | tweek |
|
|
|
|
# costs | costs | costs |
|
|
|
|
# overridden_costs | overridden_costs | overridden_costs |
|
|
|
|
# units | hours | units |
|
|
|
|
# activity_id | activity_id | -1 |
|
|
|
|
# cost_type_id | -1 | cost_type_id |
|
|
|
|
# type | "TimeEntry" | "CostEntry" |
|
|
|
|
# count | 1 | 1 |
|
|
|
|
# |
|
|
|
|
# Also: This _should_ handle joining activities and cost_types, as the logic differs for time_entries |
|
|
|
|
# and cost_entries. |
|
|
|
|
# |
|
|
|
|
# @param [#table_name] model The model to map |
|
|
|
|
# @return [CostQuery::SqlStatement] Generated statement |
|
|
|
|
def self.unified_entry(model) |
|
|
|
|
table = table_name_for model |
|
|
|
|
new(table).tap do |query| |
|
|
|
|
query.select COMMON_FIELDS |
|
|
|
|
query.desc = "Subquery for #{table}" |
|
|
|
|
query.select({ |
|
|
|
|
:count => 1, :id => [model, :id], :display_costs => 1, |
|
|
|
|
:real_costs => switch("#{table}.overridden_costs IS NULL" => [model, :costs], :else => [model, :overridden_costs]), |
|
|
|
|
:week => iso_year_week(:spent_on, model), |
|
|
|
|
:singleton_value => 1 |
|
|
|
|
}) |
|
|
|
|
#FIXME: build this subquery from a sql_statement |
|
|
|
|
query.from "(SELECT *, #{typed :text, model.model_name} AS type FROM #{table}) AS #{table}" |
|
|
|
|
send("unify_#{table}", query) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
## |
|
|
|
|
# Applies logic for mapping time entries to general entries structure. |
|
|
|
|
# |
|
|
|
|
# @param [CostQuery::SqlStatement] query The statement to adjust |
|
|
|
|
def self.unify_time_entries(query) |
|
|
|
|
query.select :activity_id, :units => :hours, :cost_type_id => -1 |
|
|
|
|
query.select :cost_type => quoted_label(:caption_labor) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
## |
|
|
|
|
# Applies logic for mapping cost entries to general entries structure. |
|
|
|
|
# |
|
|
|
|
# @param [CostQuery::SqlStatement] query The statement to adjust |
|
|
|
|
def self.unify_cost_entries(query) |
|
|
|
|
query.select :units, :cost_type_id, :activity_id => -1 |
|
|
|
|
query.select :cost_type => "cost_types.name" |
|
|
|
|
query.join CostType |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
## |
|
|
|
|
# Generates a statement based on all entries (i.e. time entries and cost entries) mapped to the general entries structure, |
|
|
|
|
# and therefore usable by filters and such. |
|
|
|
|
# |
|
|
|
|
# @return [CostQuery::SqlStatement] Generated statement |
|
|
|
|
def self.for_entries |
|
|
|
|
new unified_entry(TimeEntry).union(unified_entry(CostEntry), "entries") |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
## |
|
|
|
|
# Creates a uninon of the caller and the callee. |
|
|
|
|
# |
|
|
|
|