Index: openacs-4/contrib/packages/project-manager/tcl/task-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/tcl/Attic/task-procs.tcl,v
diff -u -r1.3 -r1.4
--- openacs-4/contrib/packages/project-manager/tcl/task-procs.tcl 26 Feb 2004 15:15:41 -0000 1.3
+++ openacs-4/contrib/packages/project-manager/tcl/task-procs.tcl 12 Mar 2004 13:44:43 -0000 1.4
@@ -10,25 +10,339 @@
}
-namespace eval project_manager::task {}
+namespace eval pm::task {}
-ad_proc -public project_manager::task::default_status_open {} {
+
+
+ad_proc -public pm::task::dependency_delete_all {
+ -task_item_id:required
+
+} {
+ Deletes all the dependencies of a task
+
+ @author Jade Rubick (jader@bread.com)
+ @creation-date 2004-02-23
+
+ @param task_item_id The task we wish to remove the dependencies from
+
+ @return
+
+ @error
+} {
+ db_dml delete_deps "delete from pm_task_dependency where task_id = :task_item_id"
+ return 1
+}
+
+
+ad_proc -public pm::task::dependency_add {
+ -task_item_id:required
+ -parent_id:required
+ -dependency_type:required
+ -project_item_id:required
+} {
+
+ Adds a dependency to a task, checking for loops in the process
+
+
+
+ We make the assumption that the following is true:
+
+
+ - no loop is created if you depend on a task already present
+ - therefore, if you add a task without creating a loop in the
+ newly created tasks, you are safe.
+
+
+ We check that the new items don't depend on each other by
+ following them if they loop more than the number of tasks in the
+ project, then we have a loop
+
+
+ The way we check for a loop is to follow the dependencies
+ until we get to a task that has already been created.
+
+ @author Jade Rubick (jader@bread.com)
+ @creation-date 2004-02-23
+
+ @param task_item_id The task that is trying to create a
+ dependency. Of course this means that the task has already been
+ created.
+
+ @param parent_id The task that we would like to create a
+ dependency on. (item_id for task, of course)
+
+ @param dependency_type Type of dependency, from pm_dependency_types
+
+ @param project_item_id The project's item_id. All dependencies are
+ created within this project
+
+ @return
+
+ @error
+} {
+
+ set project_tasks [db_list get_tasks "
+ SELECT
+ task.item_id as t_item_id
+ FROM
+ cr_items task,
+ cr_items project
+ WHERE
+ task.parent_id = project.item_id and
+ project.item_id = :project_item_id
+ "]
+
+ set loop_limit [llength $project_tasks]
+
+ if {$loop_limit > 0} {
+
+ set dep_list [list]
+ db_foreach get_dependencies "
+ SElECT
+ d.task_id as dep_task,
+ d.parent_task_id as dep_task_parent
+ FROM
+ pm_task_dependency d
+ WHERE
+ d.task_id in ([join $project_tasks ", "])
+ " {
+ lappend dep_list d-$dep_task-$dep_task_parent
+ }
+
+ # are there any loops?
+ lappend dep_list d-$task_item_id-$parent_id
+
+ foreach ti $project_tasks {
+ set task_state($ti) 0
+ }
+ nsv_array set task_node_status [array get task_state]
+
+
+ set valid_p [pm::task::verify_no_loops \
+ -current_task $task_item_id \
+ -dependency_list $dep_list]
+
+ }
+
+
+ if {[string equal $valid_p "TRUE"]} {
+ # after it passes
+ set dependency_id [db_nextval pm_task_dependency_seq]
+
+ db_dml insert_dep "insert into pm_task_dependency (dependency_id, task_id, parent_task_id, dependency_type) values (:dependency_id, :task_item_id, :parent_id, 'finish_before_start')"
+
+ } else {
+ ns_log Notice "Task $task_item_id was not added due to looping"
+ }
+
+}
+
+
+ad_proc -private pm::task::verify_no_loops {
+ {-current_task:required}
+ {-dependency_list:required}
+} {
+ Based on the dag_dfs algorithm at http://wiki.tcl.tk/3716
+
+
+
+ Determines if adding in the additional dependency would create
+ an cyclical graph or not
+
+ @author Jade Rubick (jader@bread.com)
+ @creation-date 2004-02-25
+
+ @param project_task_list
+
+ @param current_task
+
+ @param dependency_list a list of dependencies, each of the form
+ d-n1-n2 where n1 is the child and n2 is the parent. The initial
+ call to this function should include the proposed addition in
+ this list.
+
+ @return TRUE if no loops, FALSE if the proposed additon would add loops
+
+ @error
+} {
+
+ set return_val ""
+
+ array set task_state [nsv_array get task_node_status]
+
+ set task_state($current_task) 1
+
+ nsv_array set task_node_status [array get task_state]
+
+ foreach arc $dependency_list {
+ regexp {d-(.*)-(.*)} $arc match child parent
+
+ # only walk to dependencies from the current task
+ if {[string equal $child $current_task]} {
+
+ set tNode $parent
+
+ array set task_state [nsv_array get task_node_status]
+
+ set used $task_state($tNode)
+
+ if {[string equal $used 1]} {
+ return FALSE
+ }
+
+ set return_val [pm::task::verify_no_loops \
+ -current_task $parent \
+ -dependency_list $dependency_list
+ ]
+
+ if {[string equal $return_val FALSE]} {
+ return FALSE
+ }
+ }
+
+ }
+
+ array set task_state [nsv_array get task_node_status]
+
+ set task_state($current_task) 2
+
+ nsv_array set task_node_status [array get task_state]
+
+ return TRUE
+}
+
+
+
+ad_proc -public pm::task::get_item_id {
+ -task_id:required
+} {
+ Returns the task_item_id (item_id) when given the task_id (revision_id)
+
+ @author Jade Rubick (jader@bread.com)
+ @creation-date 2004-02-19
+
+ @param task_id The revision item
+
+ @return task_item_id
+
+ @error
+} {
+ set return_val [db_string get_item_id { }]
+
+ return $return_val
+}
+
+
+
+ad_proc -public pm::task::get_revision_id {
+ -task_item_id:required
+} {
+ Returns task_id (revision_id) when given the task_item_id (item_id)
+
+ @author Jade Rubick (jader@bread.com)
+ @creation-date 2004-02-19
+
+ @param task_item_id The revision item
+
+ @return task_item_id
+
+ @error
+} {
+ set return_val [db_string get_revision_id { }]
+
+ return $return_val
+}
+
+
+
+ad_proc -public pm::task::default_status_open {} {
Returns the default status value for open tasks
} {
set return_val [db_string get_default_status_open { }]
return $return_val
}
-ad_proc -public project_manager::task::default_status_closed {} {
+
+ad_proc -public pm::task::default_status_closed {} {
Returns the default status value for closed tasks
} {
set return_val [db_string get_default_status_closed { }]
return $return_val
}
-ad_proc -public project_manager::task::new {
+
+
+ad_proc -public pm::task::edit {
+ -task_item_id:required
+ -project_item_id:required
+ -title:required
+ -description:required
+ -end_date:required
+ -percent_complete:required
+ -estimated_hours_work:required
+ -estimated_hours_work_min:required
+ -estimated_hours_work_max:required
+ -actual_hours_worked:required
+ {-status_id}
+ -update_user:required
+ -update_ip:required
+ -package_id:required
+} {
+
+
+ @author Jade Rubick (jader@bread.com)
+ @creation-date 2004-02-23
+
+ @param task_item_id
+
+ @param project_item_id
+
+ @param title
+
+ @param description
+
+ @param end_date
+
+ @param percent_complete
+
+ @param estimated_hours_work
+
+ @param estimated_hours_work_min
+
+ @param estimated_hours_work_max
+
+ @param actual_hours_worked The number of hours worked to date
+
+ @param status_id The code representing the status
+
+ @param update_user The user updating the task
+
+ @param update_ip The IP address of the request
+
+ @param package_id
+
+ @return new revision_id for the task
+
+ @error
+} {
+ if {$percent_complete >= 100} {
+ set status_id [pm::task::default_status_closed]
+ }
+
+ if {![exists_and_not_null status_id]} {
+ set status_id [pm::task::default_status_open]
+ }
+
+ set return_val [db_exec_plsql new_task_revision { *SQL }]
+
+ return $return_val
+}
+
+
+
+ad_proc -public pm::task::new {
-project_id:required
-title:required
{-description ""}
@@ -44,7 +358,7 @@
-package_id:required
} {
if {![exists_and_not_null status_id]} {
- set status_id [project_manager::task::default_status_open]
+ set status_id [pm::task::default_status_open]
}
set return_val [db_exec_plsql new_task_item { *SQL }]
@@ -53,19 +367,132 @@
}
-ad_proc -public project_manager::task::get_url {
+
+ad_proc -public pm::task::get_url {
object_id
} {
# set package_id [db_string get_package_id {}]
# set package_url [site_node::get_url_from_object_id -object_id $package_id]
# set package_url [site_node::get_url_from_object_id -object_id $object_id]
#return "${package_url}task-one?task_id=$object_id"
- return "/project-manager/task-one?task_id=$object_id"
+ return {}
+ # "/project-manager/task-one?task_id=$object_id"
}
-ad_proc -public project_manager::task::process_reply {
+
+
+ad_proc -public pm::task::process_reply {
reply_id
} {
+ # return successful_p = "f"
+ return "f"
+}
+
+
+ad_proc -public pm::task::slack_time {
+ -earliest_start_j:required
+ -today_j:required
+ -latest_start_j:required
+} {
+ Return the amount of slack time
+
+ @author Jade Rubick (jader@bread.com)
+ @creation-date 2004-02-20
+
+ @param earliest_start_j Earliest start date, Julian
+
+ @param today_j today's date, in Julian
+
+ @param latest_start_j Latest start date, in Julian
+
+ @return Slack days
+
+ @error
+} {
+ if { \
+ [exists_and_not_null earliest_start_j] && \
+ [exists_and_not_null latest_start_j]} {
+
+ if {$earliest_start_j < $today_j} {
+ set slack_time "[expr $latest_start_j - $today_j] days"
+ } else {
+ set slack_time "[expr $latest_start_j - $earliest_start_j] days"
+ }
+
+ } else {
+ set slack_time "n/a"
+ }
+
}
+
+
+ad_proc -private pm::task::update_hours {
+ {-task_item_id ""}
+ {-task_revision_id ""}
+ {-update_tasks_p "t"}
+} {
+ The pm_tasks_revisions table contains a denormalized cache of the
+ total number of hours logged to it. Updates the cache from the
+ hours logged in logger and the pm_task_logger_proj_map table
+
+ @author Jade Rubick (jader@bread.com)
+ @creation-date 2004-03-04
+
+ @param task_item_id
+
+ @param task_revision_id
+
+ @param update_tasks_p If t, updates the current pm_tasks_revision
+ table in the database.
+
+ @return total logged hours
+
+ @error if neither task_item_id or task_revision_id is defined,
+ returns -1
+} {
+ if { \
+ ![info exists task_item_id] && \
+ ![info exists task_revision_id]} {
+
+ ns_log Error "Illegal parameters in pm::task::update_hours"
+ return -1
+ }
+
+ if { \
+ [exists_and_not_null task_item_id] && \
+ ![exists_and_not_null task_revision_id]} {
+
+ set task_revision_id [pm::task::get_revision_id \
+ -task_item_id $task_item_id]
+ }
+
+ if { \
+ ![exists_and_not_null task_item_id] && \
+ [exists_and_not_null task_revision_id]} {
+
+ set task_item_id [pm::task::get_item_id \
+ -task_id $task_revision_id]
+ }
+
+
+ set total_logged_hours [db_string total_hours "
+ select sum(le.value) from logger_entries le where entry_id in (select logger_entry from pm_task_logger_proj_map where task_item_id = :task_item_id) and le.variable_id = '[logger::variable::get_default_variable_id]'
+ " -default "0"]
+
+ if {[string equal $update_tasks_p "t"]} {
+
+ db_dml update_current_task "
+ UPDATE
+ pm_tasks_revisions
+ SET
+ actual_hours_worked = :total_logged_hours
+ WHERE
+ task_revision_id = :task_revision_id
+ "
+ }
+
+ return $total_logged_hours
+
+}