#projectGetWorkflowActionDefinitionOffsets = () -> # true #export default projectGetWorkflowActionDefinitionOffsets import Ember from 'ember' RecordNode = Ember.Object.extend resolved: false title: Ember.computed 'record.title', 'value_shift', -> title = @get('record.title') title = " #{title} (#{value_shift}d)" if value_shift = @get('value_shift') title OffsetNode = Ember.Object.extend record: null total_offset: 0 value_shift: 0 resulting_absolute_value: 0 WorkflowActionDefinitionOffsetNodes = Ember.Object.extend iteration_context_counter: 0 workflow_action_definitions: [] reference_date: null batch_size: 0 active_project_scenario: null forEach: -> @get('processed_workflow_action_definitions').forEach(arguments...) filterBy: -> @get('processed_workflow_action_definitions').filterBy(arguments...) get_resolved: -> @get('processed_workflow_action_definitions').filterBy('resolved') init: -> @set 'scope_workflow_action_definition_ids', @get('workflow_action_definitions').mapBy('id').toArray() @set 'processed_workflow_action_definitions', [] @set 'working_workflow_action_definitions', [] @get_workflow_action_definition_offsets() get_workflow_action_definition_offsets: -> base = @ active_scenario_identifier = @get('active_project_scenario.identifier') scope_workflow_action_definition_ids = @get('scope_workflow_action_definition_ids') first_loop_actions = [] working_workflow_action_definitions = [] @get('workflow_action_definitions').forEach (workflow_action_definition) -> action_added = false if workflow_action_definition.get('offset_type') is 'configured' workflow_action_definition.get('workflow_action_offsets').forEach (workflow_action_offset) -> return if action_added return if active_scenario_identifier and workflow_action_offset.get('project_scenario.identifier') and workflow_action_offset.get('project_scenario.identifier') isnt active_scenario_identifier if not workflow_action_offset.get('base_workflow_action_definition.content') # x_based [offset_date, offset_value] = base.get_offset_for_target(workflow_action_offset, 0) [date, value_shift] = base.get_dynamic_offset_for_target(workflow_action_offset, offset_value) absolute_value = offset_value + value_shift record_wrapper = RecordNode.create record: workflow_action_definition record_id: workflow_action_definition.get('id') offset_wrappers: [ OffsetNode.create(total_offset: absolute_value, value_shift: value_shift) ] absolute_value: absolute_value value_shift: value_shift date: date resolve_type: 'x' resolved: true resolve_level: 0 first_loop_actions.push record_wrapper action_added = true working_workflow_action_definitions.push workflow_action_definition unless action_added @set 'processed_workflow_action_definitions', first_loop_actions @set 'working_workflow_action_definitions', working_workflow_action_definitions @incrementProperty 'iteration_context_counter' #@set 'working_workflow_action_definitions', @get('workflow_action_definitions').filterBy('offset_type', 'configured') @run_critical_path_resolve_loop() resolve_level = @get('iteration_context_counter') @get('working_workflow_action_definitions').forEach (unresolved_workflow_action_definition) => # add unresolved records offset_wrappers = [] unresolved_workflow_action_definition.get('workflow_action_offsets').forEach (action_offset) -> return unless action_offset.get('base_workflow_action_definition.id') in scope_workflow_action_definition_ids # do not add offsets from other scenarios offset_wrappers.push OffsetNode.create total_offset: action_offset.get('offset_value') record: action_offset @get('processed_workflow_action_definitions').push RecordNode.create record: unresolved_workflow_action_definition record_id: unresolved_workflow_action_definition.get('id') offset_wrappers: offset_wrappers resolved: false resolve_level: resolve_level resolve_type: 'unresolved' get_dynamic_offset_for_target: (target, absolute_value) -> base_date = @get('reference_date').clone().add(absolute_value, 'day') empty = [base_date, 0] return empty unless batch_size = @get('batch_size') return empty unless threshold = target.get('batch_element_threshold_value') return empty unless threshold_exceedance = Math.floor(batch_size / (0.1 + parseInt(threshold))) # + 0.1 (delta) to exclude exact match of batch_size and threshold. First day is action day period_unit = target.get('batch_element_threshold_unit') offset_value = target.get('offset_value') operation = if offset_value < 0 then 'subtract' else 'add' if period_unit is 'businessday' operation = "business#{operation.capitalize()}" shifted_date = base_date.clone()[operation](threshold_exceedance, business_days: target.get('batch_element_threshold_business_days')) else shifted_date = base_date.clone()[operation](threshold_exceedance, period_unit) value_shift = shifted_date.diff(base_date, 'day') [shifted_date, value_shift] get_offset_for_target: (target, absolute_value) -> base_date = @get('reference_date').clone().add(absolute_value, 'day') empty = [base_date, 0] return empty unless offset_value = target.get('offset_value') period_unit = target.get('offset_unit') operation = if offset_value < 0 then 'subtract' else 'add' if period_unit is 'businessday' operation = "business#{operation.capitalize()}" shifted_date = base_date.clone()[operation](Math.abs(offset_value), business_days: target.get('offset_business_days')) else shifted_date = base_date.clone()[operation](Math.abs(offset_value), period_unit) value_shift = shifted_date.diff(base_date, 'day') #debugger if target.get('workflow_action_definition.title') is 'Initial check done' [shifted_date, value_shift] run_critical_path_resolve_loop: -> working_indices_to_be_removed = [] active_scenario_identifier = @get('active_project_scenario.identifier') processed_workflow_action_definitions = @get('processed_workflow_action_definitions') scope_workflow_action_definition_ids = @get('scope_workflow_action_definition_ids') get_dynamic_offset_for_target = @get('get_dynamic_offset_for_target').bind(@) get_offset_for_target = @get('get_offset_for_target').bind(@) resolve_level = @get('iteration_context_counter') @get('working_workflow_action_definitions').forEach (working_workflow_action_definition, working_index) -> return unless working_workflow_action_definition.get('offset_type') is 'configured' farthest_absolute_value = 0 farthest_absolute_value_value_shift = 0 farthest_result_total_offset = 0 date = null # scoping resolved_offset_wrappers = [] all_offsets_resolved = working_workflow_action_definition.get('workflow_action_offsets').every (workflow_action_offset) -> return true if active_scenario_identifier and workflow_action_offset.get('project_scenario.identifier') and workflow_action_offset.get('project_scenario.identifier') isnt active_scenario_identifier unless processed_base_workflow_action_definition_wrapper = processed_workflow_action_definitions.findBy 'record_id', workflow_action_offset.get('base_workflow_action_definition.id') if workflow_action_offset.get('base_workflow_action_definition.id') not in scope_workflow_action_definition_ids # base is not present in this scenario, do not pursue this connection return true return false processed_absolute_value = processed_base_workflow_action_definition_wrapper.get('absolute_value') [offset_date, working_offset_value] = get_offset_for_target(workflow_action_offset, processed_absolute_value) [date, current_connection_value_shift] = get_dynamic_offset_for_target(workflow_action_offset, processed_absolute_value + working_offset_value) current_connection_total_offset_value = current_connection_value_shift + working_offset_value current_connection_absolute_value = processed_absolute_value + current_connection_total_offset_value #debugger if processed_base_workflow_action_definition_wrapper.get('record.title') is 'Initial check done' #debugger if working_workflow_action_definition.get('title') is 'Initial check done' if Math.abs(current_connection_absolute_value) > Math.abs(farthest_absolute_value) farthest_absolute_value = current_connection_absolute_value farthest_absolute_value_value_shift = current_connection_value_shift farthest_result_total_offset = current_connection_total_offset_value resolved_offset_wrappers.push OffsetNode.create record: workflow_action_offset value_shift: current_connection_value_shift total_offset: current_connection_total_offset_value resulting_absolute_value: current_connection_absolute_value true # indicate processed_base_workflow_action_definition_wrapper found for all_offsets_resolved value if all_offsets_resolved and resolved_offset_wrappers.length record_wrapper = RecordNode.create record: working_workflow_action_definition record_id: working_workflow_action_definition.get('id') offset_wrappers: resolved_offset_wrappers value_shift: farthest_absolute_value_value_shift absolute_value: farthest_absolute_value date: date resolved: true resolve_level: resolve_level resolve_type: 'critical-path' processed_workflow_action_definitions.push record_wrapper working_indices_to_be_removed.push working_index if working_indices_to_be_removed.length @get('working_workflow_action_definitions').splice(working_indices_to_be_removed.pop(), 1) while working_indices_to_be_removed.length @run_critical_path_resolve_loop() else @incrementProperty 'iteration_context_counter' @run_unresolved_tree_resolve_loop() run_unresolved_tree_resolve_loop: -> working_indices_to_be_removed = [] active_scenario_identifier = @get('active_project_scenario.identifier') processed_workflow_action_definitions = @get('processed_workflow_action_definitions') scope_workflow_action_definition_ids = @get('scope_workflow_action_definition_ids') get_offset_for_target = @get('get_offset_for_target').bind(@) get_dynamic_offset_for_target = @get('get_dynamic_offset_for_target').bind(@) resolve_level = @get('iteration_context_counter') @get('working_workflow_action_definitions').forEach (working_workflow_action_definition, working_index) -> return unless working_workflow_action_definition.get('offset_type') is 'configured' farthest_absolute_value = 0 farthest_absolute_value_value_shift = 0 farthest_result_total_offset = 0 date = null # scoping resolved_offset_wrappers = [] working_workflow_action_definition.get('workflow_action_offsets').forEach (workflow_action_offset) -> return if active_scenario_identifier and workflow_action_offset.get('project_scenario.identifier') and workflow_action_offset.get('project_scenario.identifier') isnt active_scenario_identifier return unless workflow_action_offset.get('base_workflow_action_definition.id') in scope_workflow_action_definition_ids return unless processed_base_workflow_action_definition_wrapper = processed_workflow_action_definitions.findBy 'record_id', workflow_action_offset.get('base_workflow_action_definition.id') processed_absolute_value = processed_base_workflow_action_definition_wrapper.get('absolute_value') [offset_date, working_offset_value] = get_offset_for_target(workflow_action_offset, processed_absolute_value) [date, current_connection_value_shift] = get_dynamic_offset_for_target(workflow_action_offset, processed_absolute_value + working_offset_value) current_connection_total_offset_value = current_connection_value_shift + working_offset_value current_connection_absolute_value = processed_absolute_value + current_connection_total_offset_value #debugger if processed_base_workflow_action_definition_wrapper.get('record.title') is 'Initial check done' #debugger if working_workflow_action_definition.get('title') is 'Initial check done' if Math.abs(current_connection_absolute_value) > Math.abs(farthest_absolute_value) farthest_absolute_value = current_connection_absolute_value farthest_absolute_value_value_shift = current_connection_value_shift farthest_result_total_offset = current_connection_total_offset_value resolved_offset_wrappers.push OffsetNode.create record: workflow_action_offset value_shift: current_connection_value_shift total_offset: current_connection_total_offset_value resulting_absolute_value: current_connection_absolute_value if resolved_offset_wrappers.length record_wrapper = RecordNode.create record: working_workflow_action_definition record_id: working_workflow_action_definition.get('id') offset_wrappers: resolved_offset_wrappers # .clone()? value_shift: farthest_absolute_value_value_shift absolute_value: farthest_absolute_value date: date resolved: true resolve_level: resolve_level resolve_type: 'with-non-rooted-offsets' processed_workflow_action_definitions.push record_wrapper working_indices_to_be_removed.push working_index if working_indices_to_be_removed.length @get('working_workflow_action_definitions').splice(working_indices_to_be_removed.pop(), 1) while working_indices_to_be_removed.length @run_critical_path_resolve_loop() else @run_offset_forwarding_loop() run_offset_forwarding_loop: -> working_indices_to_be_removed = [] active_scenario_identifier = @get('active_project_scenario.identifier') processed_workflow_action_definitions = @get('processed_workflow_action_definitions') scope_workflow_action_definition_ids = @get('scope_workflow_action_definition_ids') get_offset_for_target = @get('get_offset_for_target').bind(@) get_dynamic_offset_for_target = @get('get_dynamic_offset_for_target').bind(@) resolve_level = @get('iteration_context_counter') @get('working_workflow_action_definitions').forEach (working_workflow_action_definition, working_index) -> farthest_absolute_value = 0 farthest_absolute_value_value_shift = 0 farthest_result_total_offset = 0 date = null # scoping resolved_offset_wrappers = [] working_workflow_action_definition.get('dependent_workflow_action_offsets').forEach (workflow_action_offset) -> return if active_scenario_identifier and workflow_action_offset.get('project_scenario.identifier') and workflow_action_offset.get('project_scenario.identifier') isnt active_scenario_identifier return unless workflow_action_offset.get('workflow_action_definition.id') in scope_workflow_action_definition_ids return unless processed_base_workflow_action_definition_wrapper = processed_workflow_action_definitions.findBy 'record_id', workflow_action_offset.get('workflow_action_definition.id') #return if workflow_action_offset.get('workflow_action_definition.offset_type') is 'none' # do not resolve on none offset typed nodes processed_absolute_value = processed_base_workflow_action_definition_wrapper.get('absolute_value') [offset_date, working_offset_value] = get_offset_for_target(workflow_action_offset, processed_absolute_value) [date, current_connection_value_shift] = get_dynamic_offset_for_target(workflow_action_offset, processed_absolute_value + working_offset_value) current_connection_total_offset_value = current_connection_value_shift + working_offset_value #NOTE MINUS!!!!!!!!!!!!!!!!!!!!! current_connection_absolute_value = processed_absolute_value - current_connection_total_offset_value #debugger if processed_base_workflow_action_definition_wrapper.get('record.title') is 'Initial check done' #debugger if working_workflow_action_definition.get('title') is 'Initial check done' if Math.abs(current_connection_absolute_value) > Math.abs(farthest_absolute_value) farthest_absolute_value = current_connection_absolute_value farthest_absolute_value_value_shift = current_connection_value_shift farthest_result_total_offset = current_connection_total_offset_value resolved_offset_wrappers.push OffsetNode.create record: workflow_action_offset value_shift: current_connection_value_shift total_offset: current_connection_total_offset_value resulting_absolute_value: current_connection_absolute_value if resolved_offset_wrappers.length record_wrapper = RecordNode.create record: working_workflow_action_definition record_id: working_workflow_action_definition.get('id') offset_wrappers: resolved_offset_wrappers # .clone()? value_shift: farthest_absolute_value_value_shift absolute_value: farthest_absolute_value date: date resolved: true resolve_level: resolve_level resolve_type: 'offset-lookup-inversion' processed_workflow_action_definitions.push record_wrapper working_indices_to_be_removed.push working_index if working_indices_to_be_removed.length @get('working_workflow_action_definitions').splice(working_indices_to_be_removed.pop(), 1) while working_indices_to_be_removed.length @run_critical_path_resolve_loop() export default WorkflowActionDefinitionOffsetNodes