Class: WorkEffort
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- WorkEffort
- Includes:
- ErpTechSvcs::Utils::DefaultNestedSetMethods
- Defined in:
- app/models/work_effort.rb
Overview
Table Definition ########################### create_table “work_efforts”, :force => true do |t|
t.integer "parent_id"
t.integer "lft"
t.integer "rgt"
t.integer "facility_id"
t.integer "projected_cost_money_id"
t.integer "actual_cost_money_id"
t.integer "fixed_asset_id"
t.integer "work_effort_purpose_type_id"
t.integer "work_effort_type_id"
t.string "description"
t.string "type"
t.datetime "start_at"
t.datetime "end_at"
t.integer "work_effort_record_id"
t.string "work_effort_record_type"
t.integer "work_effort_item_id"
t.string "work_effort_item_type"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.text "comments"
t.integer "percent_done"
t.integer "duration"
t.string "duration_unit"
t.integer "effort"
t.string "effort_unit"
t.datetime "base_line_start_at"
t.datetime "base_line_end_at"
t.integer "base_line_percent_done"
t.integer "project_id"
t.text "custom_fields"
end
add_index “work_efforts”, [“end_at”], :name => “index_work_efforts_on_end_at” add_index “work_efforts”, [“fixed_asset_id”], :name => “index_work_efforts_on_fixed_asset_id” add_index “work_efforts”, [“project_id”], :name => “work_effort_project_idx” add_index “work_efforts”, [“work_effort_item_type”, “work_effort_item_id”], :name => “work_item_idx” add_index “work_efforts”, [“work_effort_record_id”, “work_effort_record_type”], :name => “work_effort_record_id_type_idx”
Constant Summary collapse
- @@task_status_complete_iid =
'task_status_complete'
- @@task_status_in_progress_iid =
'task_status_in_progress'
- @@task_resource_status_complete_iid =
'task_resource_status_complete'
Class Method Summary collapse
-
.apply_filters(filters, statement) ⇒ ActiveRecord::Relation
Filter records.
-
.scope_by_dba_organization(dba_organization) ⇒ ActiveRecord::Relation
(also: scope_by_dba)
scope by dba organization.
-
.scope_by_party(party, options = {}) ⇒ ActiveRecord::Relation
scope by party.
-
.scope_by_party_assignment(party, options = {}) ⇒ ActiveRecord::Relation
scope by work efforts assigned to the passed party.
-
.scope_by_project(project) ⇒ ActiveRecord::Relation
scope by project.
-
.scope_by_user(user, options = {}) ⇒ ActiveRecord::Relation
scope by work efforts assigned to the passed user.
Instance Method Summary collapse
-
#assigned_parties(role_types = ['work_resource']) ⇒ Array
Get assigned parties by role type.
-
#assigned_roles ⇒ Array
get all the assigned roles.
-
#calculate_children_totals ⇒ Object
Calculate totals for children.
-
#completed? ⇒ Boolean
return true if this effort has been completed, false otherwise.
-
#current_status=(args) ⇒ Object
set current status of entity.
- #dba_organization ⇒ Object
-
#descendants_complete?(ignored_id = nil) ⇒ Boolean
Check if all this WorkEfforts descendants are complete.
-
#description_of_assigned_parties(role_types = ['work_resource']) ⇒ Array
Get comma sepeated description of all Parties assigned.
-
#finished? ⇒ Boolean
return true if this effort has been completed, false otherwise.
- #has_assigned_parties? ⇒ Boolean
- #has_time_entries? ⇒ Boolean
- #is_complete? ⇒ Boolean
-
#party_assigned?(party, role_types = ['work_resource']) ⇒ Boolean
Returns true if the party is assigned to WorkEffort.
-
#role_types ⇒ Object
(also: #role_type_assignments)
How is a work effort assigned, it can be assigned to party roles which allow for generic assignment.
-
#roll_up ⇒ Object
Roll up totals to parents.
-
#start(initial_status = '') ⇒ Object
start work effort with initial_status (string).
-
#started? ⇒ Boolean
return true if this effort has been started, false otherwise.
-
#status ⇒ String
get the current status of this work_effort.
-
#time_entries_allowed?(party) ⇒ Boolean
Check if a party is allowed to enter time aganist this Work Effort.
-
#to_data_hash ⇒ Hash
converts this record a hash data representation.
- #to_label ⇒ Object
- #to_s ⇒ Object
-
#total_hours ⇒ Object
get total hours for this WorkEffort by TimeEntries.
-
#total_hours_in_seconds ⇒ Object
get total hours for this WorkEffort by TimeEntries.
-
#work_effort_biz_txn_events ⇒ Object
What BizTxnEvents have been related to this WorkEffort.
-
#work_effort_fixed_asset_assignments ⇒ Object
What Fixed Assets (tools, equipment) are used in the execution of this Work Effort.
-
#work_effort_inventory_assignments ⇒ Object
What Inventory Items are used in the execution of this Work Effort.
-
#work_effort_party_assignments ⇒ Object
How is this Work Effort is assigned.
-
#work_effort_record ⇒ Object
Allow for polymorphic subtypes of this class.
-
#work_order_item_fulfillments ⇒ Object
How is this Work Effort related to Work Order Items (order_line_items).
Class Method Details
.apply_filters(filters, statement) ⇒ ActiveRecord::Relation
Filter records
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'app/models/work_effort.rb', line 119 def apply_filters(filters, statement) work_efforts_tbl = WorkEffort.arel_table # filter by description unless filters[:description].blank? statement = statement.where(work_efforts_tbl[:description].matches("%#{filters[:description]}%")) end # filter by WorkEffortType unless filters[:work_effort_type_iids].blank? statement = statement.where(work_effort_type_id: WorkEffortType.where(internal_identifier: filters[:work_effort_type_iids])) end # filter by Status unless filters[:status].blank? statement = statement.with_current_status(filters[:status].split(',')) end # filter by start_at unless filters[:start_date].blank? statement = statement.where(work_efforts_tbl[:start_at].gteq(Date.parse(filters[:start_date]))) end # filter by end_at unless filters[:end_date].blank? statement = statement.where(work_efforts_tbl[:end_at].lteq(Date.parse(filters[:end_date]))) end # filter by assigned to unless filters[:assigned_to_ids].blank? work_effort_party_assignments_tbl = WorkEffortPartyAssignment.arel_table statement = statement.joins(:work_effort_party_assignments) .where(work_effort_party_assignments_tbl[:role_type_id].in(RoleType.find_child_role_types([RoleType.work_resource]).collect(&:id))) .where(work_effort_party_assignments_tbl[:party_id].in(filters[:assigned_to_ids])) end # filter by project unless filters[:project_ids].blank? statement = statement.where(work_efforts_tbl[:project_id].in(filters[:project_ids])) end # filter by parties unless filters[:parties].blank? data = JSON.parse(filters[:parties]) statement = statement.scope_by_party(data['party_ids'].split(','), {role_types: RoleType.where('internal_identifier' => data['role_types'].split(','))}) end statement end |
.scope_by_dba_organization(dba_organization) ⇒ ActiveRecord::Relation Also known as: scope_by_dba
scope by dba organization
181 182 183 |
# File 'app/models/work_effort.rb', line 181 def scope_by_dba_organization(dba_organization) scope_by_party(dba_organization, {role_types: [RoleType.iid('dba_org')]}) end |
.scope_by_party(party, options = {}) ⇒ ActiveRecord::Relation
scope by party
or an array of Party ids
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'app/models/work_effort.rb', line 205 def scope_by_party(party, ={}) table_alias = String.random if [:role_types] joins("inner join entity_party_roles as #{table_alias} on #{table_alias}.entity_record_type = 'WorkEffort' and #{table_alias}.entity_record_id = work_efforts.id and #{table_alias}.role_type_id in (#{RoleType.find_child_role_types([:role_types]).collect(&:id).join(',')}) and #{table_alias}.party_id in (#{Party.select('id').where(id: party).to_sql})") else joins("inner join entity_party_roles as #{table_alias} on #{table_alias}.entity_record_type = 'WorkEffort' and #{table_alias}.entity_record_id = work_efforts.id and #{table_alias}.party_id in (#{Party.select('id').where(id: party).to_sql})") end end |
.scope_by_party_assignment(party, options = {}) ⇒ ActiveRecord::Relation
scope by work efforts assigned to the passed party
239 240 241 242 243 244 245 246 247 |
# File 'app/models/work_effort.rb', line 239 def scope_by_party_assignment(party, ={}) statement = joins("join work_effort_party_assignments wepa on wepa.work_effort_id = work_efforts.id and wepa.party_id = #{party.id}") if [:role_types] statement = statement.where("wepa.role_type_id" => RoleType.find_child_role_types([:role_types])) end statement end |
.scope_by_project(project) ⇒ ActiveRecord::Relation
scope by project
or an array of Project ids
193 194 195 |
# File 'app/models/work_effort.rb', line 193 def scope_by_project(project) where(project_id: project) end |
.scope_by_user(user, options = {}) ⇒ ActiveRecord::Relation
scope by work efforts assigned to the passed user
228 229 230 |
# File 'app/models/work_effort.rb', line 228 def scope_by_user(user, ={}) scope_by_party_assignment(user.party, ) end |
Instance Method Details
#assigned_parties(role_types = ['work_resource']) ⇒ Array
Get assigned parties by role type
266 267 268 269 270 271 272 |
# File 'app/models/work_effort.rb', line 266 def assigned_parties(role_types=['work_resource']) role_types = RoleType.find_child_role_types(role_types) Party.joins(work_effort_party_assignments: :role_type) .where(role_types: {id: role_types}) .where(work_effort_party_assignments: {work_effort_id: self.id}) end |
#assigned_roles ⇒ Array
get all the assigned roles
298 299 300 |
# File 'app/models/work_effort.rb', line 298 def assigned_roles self.role_types.collect(&:description).join(',') end |
#calculate_children_totals ⇒ Object
Calculate totals for children
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 |
# File 'app/models/work_effort.rb', line 437 def calculate_children_totals self.start_at = self.descendants.order('start_at asc').first.start_at self.end_at = self.descendants.order('end_at desc').last.end_at lowest_duration_unit = nil duration_total = nil percent_done_total = 0.0 self.descendants.collect do |child| if child.leaf? if child.duration and child.duration > 0 duration_total = 0.0 if duration_total.nil? duration_in_hours = ErpWorkEffort::Services::UnitConverter.convert_unit(child.duration.to_f, child.duration_unit.to_sym, :h) percent_done_total += (duration_in_hours.to_f * (child.percent_done.to_f / 100)) if lowest_duration_unit.nil? || ErpWorkEffort::Services::UnitConverter.new(lowest_duration_unit) > child.duration_unit.to_sym lowest_duration_unit = child.duration_unit.to_sym end duration_total += duration_in_hours end end end if duration_total self.duration_unit = lowest_duration_unit.to_s if lowest_duration_unit != :h self.duration = ErpWorkEffort::Services::UnitConverter.convert_unit(duration_total.to_f, :h, lowest_duration_unit) else self.duration = duration_total end self.percent_done = (((percent_done_total / duration_total.to_f).round(2)) * 100) end lowest_effort_unit = nil effort_total = nil self.descendants.collect do |child| if child.leaf? if child.effort and child.effort > 0 effort_total = 0.0 if effort_total.nil? if lowest_effort_unit.nil? || ErpWorkEffort::Services::UnitConverter.new(lowest_effort_unit) > child.effort_unit.to_sym lowest_effort_unit = child.effort_unit.to_sym end effort_total += ErpWorkEffort::Services::UnitConverter.convert_unit(child.effort.to_f, child.effort_unit.to_sym, :h) end end end if effort_total self.effort_unit = lowest_effort_unit.to_s if lowest_effort_unit != :h self.effort = ErpWorkEffort::Services::UnitConverter.convert_unit(effort_total.to_f, :h, lowest_effort_unit) else self.effort = effort_total end end self.save! end |
#completed? ⇒ Boolean
return true if this effort has been completed, false otherwise
319 320 321 |
# File 'app/models/work_effort.rb', line 319 def completed? finished_at.nil? ? false : true end |
#current_status=(args) ⇒ Object
set current status of entity.
This is overriding the default method to update the task assignments as well if the status is set to complete
TrackedStatusType to set, a TrackedStatusType instance, or three params the status, options and party_id
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
# File 'app/models/work_effort.rb', line 372 def current_status=(args) super(args) if args.is_a?(Array) status = args[0] else status = args end if status.is_a? TrackedStatusType status = status.internal_identifier end if status == @@task_status_complete_iid complete! else update_parent_status! end end |
#dba_organization ⇒ Object
258 259 260 |
# File 'app/models/work_effort.rb', line 258 def dba_organization find_party_with_role(RoleType.dba_org) end |
#descendants_complete?(ignored_id = nil) ⇒ Boolean
Check if all this WorkEfforts descendants are complete. An optional ignored_id can be passed for a node that you don’t want to check if it is complete
397 398 399 400 401 402 403 404 405 406 407 408 409 410 |
# File 'app/models/work_effort.rb', line 397 def descendants_complete?(ignored_id=nil) all_complete = true descendants.each do |node| unless node.id == ignored_id if !node.is_complete? all_complete = false break end end end all_complete end |
#description_of_assigned_parties(role_types = ['work_resource']) ⇒ Array
Get comma sepeated description of all Parties assigned
289 290 291 292 293 |
# File 'app/models/work_effort.rb', line 289 def description_of_assigned_parties(role_types=['work_resource']) assigned_parties(role_types).collect do |item| item.party.description end.join(',') end |
#finished? ⇒ Boolean
return true if this effort has been completed, false otherwise
326 327 328 |
# File 'app/models/work_effort.rb', line 326 def finished? completed? end |
#has_assigned_parties? ⇒ Boolean
342 343 344 |
# File 'app/models/work_effort.rb', line 342 def has_assigned_parties? self.work_effort_party_assignments.count != 0 end |
#has_time_entries? ⇒ Boolean
338 339 340 |
# File 'app/models/work_effort.rb', line 338 def has_time_entries? self.time_entries.count != 0 end |
#is_complete? ⇒ Boolean
412 413 414 |
# File 'app/models/work_effort.rb', line 412 def is_complete? (current_status == @@task_status_complete_iid) end |
#party_assigned?(party, role_types = ['work_resource']) ⇒ Boolean
Returns true if the party is assigned to WorkEffort
278 279 280 281 282 283 |
# File 'app/models/work_effort.rb', line 278 def party_assigned?(party, role_types=['work_resource']) !WorkEffort.joins(work_effort_party_assignments: :role_type) .where(role_types: {id: RoleType.find_child_role_types(role_types)}) .where(work_effort_party_assignments: {work_effort_id: self.id}) .where(work_effort_party_assignments: {party_id: party.id}).first.nil? end |
#role_types ⇒ Object Also known as: role_type_assignments
How is a work effort assigned, it can be assigned to party roles which allow for generic assignment.
78 |
# File 'app/models/work_effort.rb', line 78 has_and_belongs_to_many :role_types |
#roll_up ⇒ Object
Roll up totals to parents
503 504 505 506 507 508 |
# File 'app/models/work_effort.rb', line 503 def roll_up if self.parent self.parent.calculate_children_totals self.parent.roll_up end end |
#start(initial_status = '') ⇒ Object
start work effort with initial_status (string)
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'app/models/work_effort.rb', line 349 def start(initial_status='') effort = self unless self.descendants.flatten!.nil? children = self.descendants.flatten effort = children.last end if current_status.nil? effort.current_status = initial_status effort.start_at = DateTime.now effort.save else raise 'Effort Already Started' end end |
#started? ⇒ Boolean
return true if this effort has been started, false otherwise
312 313 314 |
# File 'app/models/work_effort.rb', line 312 def started? current_status.nil? ? false : true end |
#status ⇒ String
get the current status of this work_effort
305 306 307 |
# File 'app/models/work_effort.rb', line 305 def status current_status end |
#time_entries_allowed?(party) ⇒ Boolean
Check if a party is allowed to enter time aganist this Work Effort
334 335 336 |
# File 'app/models/work_effort.rb', line 334 def time_entries_allowed?(party) self.party_assigned?(party) and self.current_status != @@task_status_complete_iid end |
#to_data_hash ⇒ Hash
converts this record a hash data representation
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 |
# File 'app/models/work_effort.rb', line 513 def to_data_hash data = to_hash(only: [ :id, {leaf?: :leaf}, :parent_id, :description, :start_at, :end_at, :percent_done, :duration, :duration_unit, :effort, :effort_unit, :comments, :sequence, :created_at, :updated_at, :current_status ] ) data[:status] = self.try(:current_status_application).try(:to_data_hash) data[:work_effort_type] = self.try(:work_effort_type).try(:to_data_hash) data end |
#to_label ⇒ Object
254 255 256 |
# File 'app/models/work_effort.rb', line 254 def to_label self.description end |
#to_s ⇒ Object
250 251 252 |
# File 'app/models/work_effort.rb', line 250 def to_s self.description end |
#total_hours ⇒ Object
get total hours for this WorkEffort by TimeEntries
427 428 429 430 431 432 433 |
# File 'app/models/work_effort.rb', line 427 def total_hours if self.leaf? time_entries.all.sum { |time_entry| time_entry.hours } else self.descendants.collect(&:total_hours) end end |
#total_hours_in_seconds ⇒ Object
get total hours for this WorkEffort by TimeEntries
418 419 420 421 422 423 424 |
# File 'app/models/work_effort.rb', line 418 def total_hours_in_seconds if leaf? time_entries.sum(:regular_hours_in_seconds) else descendants.collect(&:total_hours_in_seconds) end end |
#work_effort_biz_txn_events ⇒ Object
What BizTxnEvents have been related to this WorkEffort
98 |
# File 'app/models/work_effort.rb', line 98 has_many :work_effort_biz_txn_events, :dependent => :destroy |
#work_effort_fixed_asset_assignments ⇒ Object
What Fixed Assets (tools, equipment) are used in the execution of this Work Effort
94 |
# File 'app/models/work_effort.rb', line 94 has_many :work_effort_fixed_asset_assignments, :dependent => :destroy |
#work_effort_inventory_assignments ⇒ Object
What Inventory Items are used in the execution of this Work Effort
90 |
# File 'app/models/work_effort.rb', line 90 has_many :work_effort_inventory_assignments, :dependent => :destroy |
#work_effort_party_assignments ⇒ Object
How is this Work Effort is assigned
82 |
# File 'app/models/work_effort.rb', line 82 has_many :work_effort_party_assignments, :dependent => :destroy |
#work_effort_record ⇒ Object
Allow for polymorphic subtypes of this class
102 |
# File 'app/models/work_effort.rb', line 102 belongs_to :work_effort_record, :polymorphic => true |
#work_order_item_fulfillments ⇒ Object
How is this Work Effort related to Work Order Items (order_line_items)
74 |
# File 'app/models/work_effort.rb', line 74 has_many :work_order_item_fulfillments, :dependent => :destroy |