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.4.2.24 -r1.4.2.25 --- openacs-4/contrib/packages/project-manager/tcl/task-procs.tcl 8 Oct 2004 21:25:04 -0000 1.4.2.24 +++ openacs-4/contrib/packages/project-manager/tcl/task-procs.tcl 26 Oct 2004 01:22:27 -0000 1.4.2.25 @@ -13,7 +13,24 @@ namespace eval pm::task {} +ad_proc -public pm::task::name { + {-task_item_id:required} +} { + Returns the name of the task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-25 + + @param task_item_id + @return + + @error -1 +} { + return [db_string get_name { } -default "-1"] +} + + ad_proc -public pm::task::options_list { {-edit_p "f"} -project_item_id @@ -81,7 +98,7 @@ SELECT r.item_id, r.title as task_title - FROM + FROM pm_tasks_revisionsx r, cr_items i, pm_tasks_active t @@ -147,6 +164,173 @@ } +ad_proc -public pm::task::options_list_html { + {-edit_p "f"} + -project_item_id + {-task_item_id ""} + {-dependency_task_id ""} + {-dependency_task_ids ""} + {-number "0"} + {-depends_on_new ""} + {-current_number "0"} +} { + Returns a list of options suiteable for HTML. + Contains a list of possible tasks that this task can + depend upon, or selected. These tasks are limited to just the + one project. + +

+ + There is one special case that we handle: if you are creating new + tasks (not editing), you can have them depend on each other. + So if you create two tasks at the same time, you may want task + 2 to depend on task 1. Instead of a task_item_id, we then + specify a value of this form: + +

+ numX +
+ + where X represents the number of the new task, ranging from 1 + to n. + +

+ + To be more efficient when creating multiple tasks at the same + time, we should cache the database calls. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-13 + + @param edit_p Is this for a task being edited? Or a new task? + + @param project_item_id The project we're finding tasks from + + @param task_item_id The task ID. This is used because we do not + want a task to depend on itself, so it is excluded from the list. + + @param dependency_task_ids For edited tasks, the current task_ids + that it depends on. Used because sometimes it can be closed, and + it wouldn't otherwise appear on the list. This is a list. + + @param dependency_task_id For edited tasks, the current task that + it depends on, used for setting the default option in HTML. + + @param number When the list is returned, it includes entries for + number new tasks, in the numX format described in these docs. + + @param depends_on_new When you're using a process, you want the + dependency to be on other new tasks. The format for this should + be num1 num2, etc.. So we make the default if this parameter is set. + + @param current_number The current number. Used for new tasks. It + prevents allowing dependencies on the task being created. + + @return + + @error +} { + + # get tasks this task can depend on + + if {[exists_and_not_null dependency_task_ids]} { + + set union_clause " + UNION + SELECT + r.item_id, + r.title as task_title + FROM + pm_tasks_revisionsx r, + cr_items i, + pm_tasks_active t + WHERE + r.parent_id = :project_item_id and + r.revision_id = i.live_revision and + i.item_id = t.task_id + and t.task_id in ([join $dependency_task_ids ","])" + } else { + set union_clause "" + } + + set keys [list] + + db_foreach get_dependency_tasks { } { + set options($task_title) $item_id + lappend keys $task_title + } + + set keys [lsort $keys] + + # --------------------------------------------------------------- + # Start setting up the output. + # These are for new tasks, the already created tasks are added to + # the list later. + # --------------------------------------------------------------- + + set dependency_options_full " " + + if {[string is false $edit_p]} { + + # now set up dependency options + + for {set j 1} {$j <= $number} {incr j} { + + if {[string equal $depends_on_new $j]} { + set selected "selected=\"selected\" " + } else { + set selected "" + } + + if {![string equal $current_number $j]} { + append dependency_options_full " " + } + } + } + + # ------------------------------------------------- + # Now add the tasks that are already in the project + # ------------------------------------------------- + + + if {[string is true $edit_p]} { + foreach key $keys { + + # for editing tasks, we skip ourselves (because depending on + # ourselves just sometimes isn't an option) + if {![string equal $task_item_id $options($key)]} { + + if {[string equal $options($key) $dependency_task_id]} { + set selected "selected=\"selected\" " + } else { + set selected "" + } + + # check for case when there is a quote in the name of + # a task. We have to filter this out, or we get an + # error. -- not sure what this comment is for -- JR + + + append dependency_options_full " " + } + } + } else { + + foreach key $keys { + + # check for case when there is a quote in the name of a + # task. We have to filter this out, or we get an error. -- + # not sure what this comment is for -- JR + + append dependency_options_full " " + } + } + + + return $dependency_options_full +} + + ad_proc -public pm::task::dependency_delete_all { -task_item_id:required @@ -156,13 +340,14 @@ @author Jade Rubick (jader@bread.com) @creation-date 2004-02-23 - @param task_item_id The task we wish to remove the dependencies from + @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" + db_dml delete_deps { } + return 1 } @@ -214,16 +399,7 @@ @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 project_tasks [db_list get_tasks { }] # we do not allow tasks to depend on items outside of their # project. So if it's not in the list of tasks for that project, @@ -239,15 +415,7 @@ 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 ", "]) - " { + db_foreach get_dependencies { } { lappend dep_list d-$dep_task-$dep_task_parent } @@ -266,12 +434,11 @@ } - - if {[string equal $valid_p "TRUE"]} { + if {[string is true $valid_p]} { # 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')" + db_dml insert_dep { } } else { ns_log Notice "Task dependency for $task_item_id on $parent_id was not added due to looping or being outside of the current project" @@ -457,8 +624,6 @@ -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 @@ -491,10 +656,6 @@ @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 @@ -505,56 +666,42 @@ @error } { - if {![exists_and_not_null status_id]} { - set status_id [pm::task::current_status \ - -task_item_id $task_item_id] - } - # simple sanity check for min and max estimated hours if {$estimated_hours_work_min > $estimated_hours_work_max} { set temp $estimated_hours_work_max set estimated_hours_work_max $estimated_hours_work_min set estimated_hours_work_min $temp } - set return_val [db_exec_plsql new_task_revision { *SQL }] + if {$percent_complete >= 100} { - # we have to update all logged hours to make sure the hours are - # updated whenever the project is changed. + set status_id [pm::task::default_status_closed] - set logger_project [pm::project::get_logger_project -project_item_id $project_item_id] + } elseif {$percent_complete < 100} { - db_dml update_logger_entries { - UPDATE - logger_entries - SET - project_id = :logger_project - WHERE - entry_id in - (select logger_entry from pm_task_logger_proj_map where task_item_id = :task_item_id) + set status_id [pm::task::default_status_open] } - # if the we've done 100% of the work, then we close the task - if {$percent_complete >= 100} { - pm::task::close \ - -task_item_id $task_item_id \ - -comment "$comment" \ - -comment_type $comment_type - } else { - # does not need comment because that's done later - pm::task::open \ - -task_item_id $task_item_id + set actual_hours_worked [pm::task::update_hours \ + -task_item_id $task_item_id] - } + set return_val [db_exec_plsql new_task_revision { *SQL }] + # we have to update all logged hours to make sure the hours are + # set to the correct project whenever the project is changed. + + set logger_project [pm::project::get_logger_project -project_item_id $project_item_id] + + db_dml update_logger_entries { } + return $return_val } ad_proc -public pm::task::new { -project_id:required - -title:required + {-title "Subject missing"} {-description ""} {-mime_type "text/plain"} {-end_date ""} @@ -564,10 +711,25 @@ {-estimated_hours_work_max "0"} {-creation_date ""} {-status_id ""} + {-process_instance_id ""} -creation_user:required -creation_ip:required -package_id:required } { + Creates a new task. + + @param process_instance_id If a process was used to create the + task, then it is linked in to that process instance, so we can + things like display only tasks that are a part of a process. + + @author Jade Rubick (jader@bread.com) + @creation-date who knows? + + @return new task_item_id + + @error + +} { if {![exists_and_not_null status_id]} { set status_id [pm::task::default_status_open] } @@ -578,9 +740,15 @@ set estimated_hours_work_min $temp } - set return_val [db_exec_plsql new_task_item { *SQL }] + set task_revision [db_exec_plsql new_task_item { *SQL }] + set task_item_id [pm::task::get_item_id \ + -task_id $task_revision] - return $return_val + if {$percent_complete >= 100} { + pm::task::close -task_item_id $task_item_id + } + + return $task_item_id } @@ -739,7 +907,7 @@ 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"]} { + if {[string is true $update_tasks_p]} { db_dml update_current_task " UPDATE @@ -865,10 +1033,9 @@ ad_proc -public pm::task::open { - -task_item_id:required + {-task_item_id:required} } { - Opens a task, and sends notifications, unless it was already - open. If it was already open, does nothing. + Opens a task. @author Jade Rubick (jader@bread.com) @creation-date 2004-04-22 @@ -879,137 +1046,15 @@ @error } { - # find out what the status of the task was, and while we're at it, - # get other interesting information about the task, in case we - # want to close it. Then we can put this info in the email. - - db_1row get_status " - SELECT - t.status, - s.status_type, - s.description as status_description, - r.title as task_title, - r.estimated_hours_work, - r.estimated_hours_work_min, - r.estimated_hours_work_max, - to_char(r.earliest_start, 'YYYY-MM-DD HH24:MI:SS') as earliest_start_ansi, - to_char(r.earliest_finish, 'YYYY-MM-DD HH24:MI:SS') as earliest_finish_ansi, - to_char(r.latest_start, 'YYYY-MM-DD HH24:MI:SS') as latest_start_ansi, - to_char(r.latest_finish, 'YYYY-MM-DD HH24:MI:SS') as latest_finish_ansi, - r.description as task_description, - r.mime_type, - project_revision.title as project_name - FROM - pm_tasks t, - cr_items task_item, - pm_task_status s, - pm_tasks_revisionsx r, - cr_items project_item, - cr_revisions project_revision - WHERE - r.parent_id = project_item.item_id and - t.task_id = task_item.item_id and - task_item.live_revision = r.revision_id and - project_item.live_revision = project_revision.revision_id and - r.item_id = t.task_id and - t.status = s.status_id and - t.task_id = :task_item_id" - - if {[string equal $status_type "o"]} { - - # this is already open - return - - } - - # set the new status - set status_code [pm::task::default_status_open] - db_dml update_status " - UPDATE - pm_tasks - SET - status = :status_code - WHERE - task_id = :task_item_id" - - # send out an email notification - - set earliest_start [lc_time_fmt $earliest_start_ansi "%x"] - set earliest_finish [lc_time_fmt $earliest_finish_ansi "%x"] - set latest_start [lc_time_fmt $latest_start_ansi "%x"] - set latest_finish [lc_time_fmt $latest_finish_ansi "%x"] - - set assignees [pm::task::assignee_email_list -task_item_id $task_item_id] - - if {[llength $assignees] > 0} { - - set to_address $assignees - - set user_id [ad_conn user_id] - - set from_address [db_string get_from_email "select email from parties where party_id = :user_id" -default "nobody@nowhere.com"] - - set task_url [pm::task::get_url $task_item_id] - - set subject "Task Reopened (was $status_description): $task_title" - - set notification_text "Task reopened, was $status_description\n\n" - - set task_description [ad_html_text_convert -from $mime_type -to "text/html" -- $task_description] - - append notification_text " -

Task overview

- - - - - - - - - -
Subject:$task_title (\#$task_item_id)
Project:$project_name
- -

Description

- - - - -
$task_description
- -

Dates:

- - - - - - - - - -
Latest start:$latest_start
Latest finish$latest_finish
-" - - pm::util::email \ - -to_addr $to_address \ - -from_addr $from_address \ - -subject $subject \ - -body $notification_text \ - -mime_type "text/html" - } - - return + db_dml update_status { } } ad_proc -public pm::task::close { - -task_item_id:required - {-comment ""} - {-comment_type "text/plain"} + {-task_item_id:required} } { - Closes a task, and sends notifications, unless it was already - closed. If it was already closed, does nothing. + Closes a task @author Jade Rubick (jader@bread.com) @creation-date 2004-04-22 @@ -1020,180 +1065,10 @@ @error } { - # find out what the status of the task was - - db_1row get_status " - SELECT - t.status, - s.status_type, - s.description as status_description, - r.title as task_title, - r.estimated_hours_work, - r.estimated_hours_work_min, - r.estimated_hours_work_max, - to_char(r.earliest_start, 'YYYY-MM-DD HH24:MI:SS') as earliest_start_ansi, - to_char(r.earliest_finish, 'YYYY-MM-DD HH24:MI:SS') as earliest_finish_ansi, - to_char(r.latest_start, 'YYYY-MM-DD HH24:MI:SS') as latest_start_ansi, - to_char(r.latest_finish, 'YYYY-MM-DD HH24:MI:SS') as latest_finish_ansi, - r.description as task_description, - r.mime_type, - project_revision.title as project_name - FROM - pm_tasks t, - cr_items task_item, - pm_task_status s, - pm_tasks_revisionsx r, - cr_items project_item, - cr_revisions project_revision - WHERE - r.parent_id = project_item.item_id and - t.task_id = task_item.item_id and - task_item.live_revision = r.revision_id and - project_item.live_revision = project_revision.revision_id and - r.item_id = t.task_id and - t.status = s.status_id and - t.task_id = :task_item_id" - - if {[string equal $status_type "c"]} { - - # this is already closed - return - - } - - # set the new status - set status_code [pm::task::default_status_closed] - db_dml update_status " - UPDATE - pm_tasks - SET - status = :status_code - WHERE - task_id = :task_item_id" + db_dml update_status { } - # send out an email notification - - set earliest_start [lc_time_fmt $earliest_start_ansi "%x"] - set earliest_finish [lc_time_fmt $earliest_finish_ansi "%x"] - set latest_start [lc_time_fmt $latest_start_ansi "%x"] - set latest_finish [lc_time_fmt $latest_finish_ansi "%x"] - - - set assignees [pm::task::assignee_email_list -task_item_id $task_item_id] - - if {[llength $assignees] > 0} { - - set to_address $assignees - - set user_id [ad_conn user_id] - - set from_address [db_string get_from_email "select email from parties where party_id = :user_id" -default "nobody@nowhere.com"] - - set last_time_stamp "" - set work_log "

Work done on this task

" - - db_foreach get_logged_time " - SELECT - to_char(le.time_stamp, 'fmDyfm fmMMfm-fmDDfm-YYYY') as time_stamp_pretty, - le.value, - le.description, - r.title as task_name, - submitter.first_names || ' ' || submitter.last_name as user_name - FROM - logger_entries le, - cr_items i, - cr_revisions r, - pm_task_logger_proj_map m, - logger_projects lp, - acs_objects ao, - acs_users_all submitter - WHERE - r.item_id = m.task_item_id and - i.live_revision = r.revision_id and - r.item_id = :task_item_id and - le.project_id = lp.project_id and - ao.object_id = le.entry_id and - le.entry_id = m.logger_entry and - ao.creation_user = submitter.user_id - ORDER BY - le.time_stamp desc" { - append work_log "" - - if {![string equal $time_stamp_pretty $last_time_stamp]} { - append work_log "\n" - - set last_time_stamp $time_stamp_pretty - - append work_log "" - } - - append work_log "
$time_stamp_pretty" - } else { - append work_log " " - } - append work_log "$user_name$description$value hrs
" - - set task_url [pm::task::get_url $task_item_id] - - set subject "Task Closed (was $status_description) $task_title" - - set notification_text "Task closed, was $status_description\n\n" - - set task_description [ad_html_text_convert -from $mime_type -to "text/html" -- $task_description] - - set comment [ad_html_text_convert -from $comment_type -to "text/html" -- $comment] - - append notification_text " -

Comment:

-$comment - -
- - - - - - - - - -
Subject:$task_title (\#$task_item_id)
Project:$project_name
-" - append notification_text "$work_log" - - append notification_text " -

Description

- - - - -
$task_description
- -

Dates:

- - - - - - - - - -
Latest start:$latest_start
Latest finish$latest_finish
-" - - - pm::util::email \ - -to_addr $to_address \ - -from_addr $from_address \ - -subject $subject \ - -body $notification_text \ - -mime_type "text/html" - } - - return } @@ -1452,26 +1327,9 @@ ad_proc -public pm::task::email_alert { -task_item_id:required - {-user_id ""} - {-assignee_id ""} - {-assignee_role_name ""} {-edit_p "t"} {-comment ""} {-comment_mime_type "text/plain"} - {-description ""} - {-description_mime_type "text/plain"} - {-old_description ""} - {-old_description_mime_type "text/plain"} - {-subject ""} - {-work ""} - {-work_min ""} - {-work_max ""} - {-project_name ""} - {-earliest_start ""} - {-earliest_finish ""} - {-latest_start ""} - {-latest_finish ""} - {-url ""} } { Sends out an email notification when changes have been made to a task @@ -1486,168 +1344,108 @@ @param task_item_id - @param user_id The user making the change - - @param assignee_id The party_id of the user assigned to the task. - - @param assignee_role_name The role name for what the party is - assigned to do - @param edit_p Is this an edited task, or a new one? t for edited, f otherwise. - @param description - - @param old_description - - @param subject The one line description of the task - - @param work Estimated hours work - - @param work_min Estimated minimimum hours work - - @param work_max Estimated maximum hours work - - @param project_name - - @param earliest_start - - @param earliest_finish - - @param latest_start - - @param latest_finish - - @param url Optionally, a URL that the user is directed to - @return @error } { - set task_term [parameter::get -parameter "Taskname" -default "Task"] - set task_term_lower [parameter::get -parameter "taskname" -default "task"] - set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "0"] + set task_term \ + [parameter::get -parameter "Taskname" -default "Task"] + set task_term_lower \ + [parameter::get -parameter "taskname" -default "task"] + set use_uncertain_completion_times_p \ + [parameter::get -parameter "UseUncertainCompletionTimesP" -default "0"] - # from address + set user_id [ad_conn user_id] - if {![exists_and_not_null $user_id]} { - set user_id [ad_conn user_id] - } + db_1row get_from_address_and_more { } - db_1row get_from_address_and_more { - SELECT - p.email as from_address, - p2.first_names || ' ' || p2.last_name as mod_username - FROM - parties p, - persons p2 - WHERE - p.party_id = :user_id and - p.party_id = p2.person_id - } + db_1row get_task_info { } - # to address + if {[string is true $edit_p]} { - if {![exists_and_not_null assignee_id]} { + # ---- + # EDIT + # ---- - # bug: we should get the list of assignees here. - ns_log Error "the proc pm::task::email_alert is not complete: assignee" - - } + set subject_out "Edited $task_term \#$task_item_id: $subject" + set intro_text "$mod_username edited this $task_term_lower" - set to_address [db_string get_email "select email from parties where party_id = :assignee_id"] + } else { - # if they left out any of the task info, then we get it from the database - if { \ - ![exists_and_not_null subject] || \ - ![exists_and_not_null work] || \ - ![exists_and_not_null work_min] || \ - ![exists_and_not_null work_max] || \ - ![exists_and_not_null project_name] || \ - ![exists_and_not_null earliest_start] || \ - ![exists_and_not_null earliest_finish] || \ - ![exists_and_not_null latest_start] || \ - ![exists_and_not_null latest_finish] \ - } { - - db_1row get_task_info { - SELECT - t.title as subject, - to_char(t.earliest_start,'MM-DD-YYYY') as earliest_start, - to_char(t.earliest_finish,'MM-DD-YYYY') as earliest_finish, - to_char(t.latest_start,'MM-DD-YYYY') as latest_start, - to_char(t.latest_finish,'MM-DD-YYYY') as latest_finish, - t.estimated_hours_work as work, - t.estimated_hours_work_min as work_min, - t.estimated_hours_work_max as work_max, - t.percent_complete, - p.title as project_name - FROM - pm_tasks_revisionsx t, - cr_items i, - cr_items project, - pm_projectsx p - WHERE - t.item_id = :task_item_id and - t.revision_id = i.live_revision and - t.item_id = i.item_id and - t.parent_id = project.item_id and - project.item_id = p.item_id and - project.live_revision = p.revision_id - } + # --- + # NEW + # --- - } - - - if {[string is true $edit_p]} { - set subject_out "Edited $task_term \#$task_item_id: $subject" - set intro_text "$mod_username edited this $task_term_lower" - } else { set subject_out "New $task_term \#$task_item_id: $subject" set intro_text "$mod_username assigned you to a new $task_term_lower" + } + if {[empty_string_p $comment]} { set comment_text "" } else { set comment_text "

Comment:

$comment

" } - - if {[exists_and_not_null url]} { - set task_url $url - } else { - set task_url "unavailable" - } + set url [pm::task::get_url $task_item_id] + set description [ad_html_text_convert -from $description_mime_type -to "text/html" -- $description] - set old_description [ad_html_text_convert -from $old_description_mime_type -to "text/html" -- $old_description] - if {![string equal $description $old_description] && [string is true $edit_p]} { - set description_out "$description

Old description:

$old_description" + set description_out $description + set assignees [db_list_of_lists get_assignees { }] + + if {[exists_and_not_null $process_instance]} { + + set process_url [pm::process::url \ + -process_instance_id $process_instance \ + -project_item_id $project_item_id] + + set process_description [pm::process::name \ + -process_instance_id $process_instance] + + set process_html " +

Process

+ + + + +
$process_description
+" } else { - set description_out $description + set process_html "" } - set notification_text "${intro_text}${comment_text} + foreach ass $assignees { + + set to_address [lindex $ass 0] + set role [lindex $ass 1] + set is_lead_p [lindex $ass 2] + + set notification_text "${intro_text}${comment_text}

Task overview

- + - +
Subject:$subject (\#$task_item_id)$subject (\#$task_item_id)
Project: $project_name
Your role:$assignee_role_name$role
+$process_html

Description

@@ -1667,13 +1465,13 @@
" - pm::util::email \ - -to_addr $to_address \ - -from_addr $from_address \ - -subject $subject_out \ - -body $notification_text \ - -mime_type "text/html" - + pm::util::email \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject_out \ + -body $notification_text \ + -mime_type "text/html" + } } @@ -1894,38 +1692,121 @@ } -ad_proc -public pm::task::process_task_info { - {-process_id:required} - {-one_line_array:required} - {-description_array:required} - {-estimated_hours_work_array:required} - {-estimated_hours_work_min_array:required} - {-estimated_hours_work_max_array:required} - {-dependency_array:required} - {-tasks_list:required} + +ad_proc -public pm::task::assignee_html { + {-number:required} + {-process_task_id ""} + {-task_item_id ""} } { - Sets a bunch of information in a set of arrays on all - process tasks for a given process + Assignee HTML for new tasks @author Jade Rubick (jader@bread.com) - @creation-date 2004-09-23 + @creation-date 2004-10-13 - @param process_id + @return + + @error +} { - @param one_line_array + # ------------------------------ + # cache these to speed it all up - @param description_array + set roles_list_of_lists [pm::role::select_list_filter] + set assignee_list_of_lists [pm::util::subsite_assignees_list_of_lists] - @param estimated_hours_work_array - @param estimated_hours_work_min_array + # Get assignments for when using processes + if {[exists_and_not_null process_task_id]} { - @param estimated_hours_work_max_array + # PROCESS - @param dependency_array + set task_assignee_list_of_lists \ + [pm::process::task_assignee_role_list \ + -process_task_id $process_task_id] - @param tasks_list + } elseif {[exists_and_not_null task_item_id]} { + # EDITING + + set task_assignee_list_of_lists \ + [pm::task::assignee_role_list \ + -task_item_id $task_item_id] + + } else { + + # NEW + + set task_assignee_list_of_lists [list] + } + + # Get assignments for when editing + + + set html "" + + foreach role_list $roles_list_of_lists { + + set role_name [lindex $role_list 0] + set role [lindex $role_list 1] + + append html " + " + + } + + append html "

$role_name

" + + foreach assignee_list $assignee_list_of_lists { + set name [lindex $assignee_list 0] + set person_id [lindex $assignee_list 1] + + if {[lsearch $task_assignee_list_of_lists [list $person_id $role]] >= 0} { + + append html " + $name +
" + + } else { + + append html " + $name +
" + } + + } + + append html "

" + + return $html +} + + +ad_proc -public pm::task::get { + {-tasks_item_id:required} + {-one_line_array:required} + {-description_array:required} + {-description_mime_type_array:required} + {-estimated_hours_work_array:required} + {-estimated_hours_work_min_array:required} + {-estimated_hours_work_max_array:required} + {-dependency_array:required} + {-percent_complete_array:required} + {-end_date_day_array:required} + {-end_date_month_array:required} + {-end_date_year_array:required} + {-project_item_id_array:required} +} { + Stuff information about tasks into several arrays + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-14 + + @param tasks_item_id a list of tasks to retrieve and stuff in + arrays + + @param one_line_array stuff one_line info in + one_line_array(task_item_id) + @return @error @@ -1934,34 +1815,411 @@ # set variables in calling environment, using names passed in upvar 1 $one_line_array one_line_arr upvar 1 $description_array description_arr + upvar 1 $description_mime_type_array description_mime_type_arr upvar 1 $estimated_hours_work_array estimated_hours_work_arr upvar 1 $estimated_hours_work_min_array estimated_hours_work_min_arr upvar 1 $estimated_hours_work_max_array estimated_hours_work_max_arr upvar 1 $dependency_array dependency_arr - upvar 1 $tasks_list process_tasks_l + upvar 1 $percent_complete_array percent_complete_arr + upvar 1 $end_date_day_array end_date_day_arr + upvar 1 $end_date_month_array end_date_month_arr + upvar 1 $end_date_year_array end_date_year_arr + upvar 1 $project_item_id_array project_item_id_arr - db_foreach get_process_tasks { } { - set one_line_arr($process_tid) $one_line - set description_arr($process_tid) $description - set estimated_hours_work_arr($process_tid) $estimated_hours_work - set estimated_hours_work_min_arr($process_tid) $estimated_hours_work_min - set estimated_hours_work_max_arr($process_tid) $estimated_hours_work_max - set dependency_arr($process_tid) $process_parent_task + set task_where_clause " and i.item_id in ([join $tasks_item_id ", "])" + db_foreach get_tasks { } { + set one_line_arr($tid) $one_line + set description_arr($tid) $description + set description_mime_type_arr($tid) $description_mime_type + set estimated_hours_work_arr($tid) $estimated_hours_work + set estimated_hours_work_min_arr($tid) $estimated_hours_work_min + set estimated_hours_work_max_arr($tid) $estimated_hours_work_max + set dependency_arr($tid) $parent_task_id + set percent_complete_arr($tid) $percent_complete + set end_date_day_arr($tid) $end_date_day + set end_date_month_arr($tid) $end_date_month + set end_date_year_arr($tid) $end_date_year + set project_item_id_arr($tid) $project + # make sure that we don't have empty values for estimated # hours work - if {[empty_string_p $estimated_hours_work_arr($process_tid)]} { - set estimated_hours_work_arr($process_tid) 0 + if {[empty_string_p $estimated_hours_work_arr($tid)]} { + set estimated_hours_work_arr($tid) 0 } - if {[empty_string_p $estimated_hours_work_min_arr($process_tid)]} { - set estimated_hours_work_min_arr($process_tid) 0 + if {[empty_string_p $estimated_hours_work_min_arr($tid)]} { + set estimated_hours_work_min_arr($tid) 0 } - if {[empty_string_p $estimated_hours_work_max_arr($process_tid)]} { - set estimated_hours_work_max_arr($process_tid) 0 + if {[empty_string_p $estimated_hours_work_max_arr($tid)]} { + set estimated_hours_work_max_arr($tid) 0 } + } + +} - lappend process_tasks_l $process_tid + +ad_proc -public pm::task::date_html { + {-selected_month ""} + {-selected_day ""} + {-selected_year ""} +} { + Returns HTML for the date widget in the task-add-edit page + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-15 + + @return + + @error +} { + for {set i 1} {$i <= 12} {incr i} { + + # numbers are in the form of 01 - 12 + if {$i < 10} { + set j "0$i" + } else { + set j $i + } + set selected_[set j] "" } + set selected_[set selected_month] "selected=\"selected\"" + + return " + + + + + + + + + + + +
+   + + +
+ Month + + Day + + Year +
" + +} + + +ad_proc -public pm::task::get_assignee_names { + {-task_item_id:required} +} { + Returns a list of assignees to a task (first name + last name) + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-20 + + @param task_item_id + + @return + + @error +} { + + return [db_list get_assignees { }] + } + + +ad_proc -public pm::task::assignee_role_list { + {-task_item_id:required} +} { + Returns a list of lists, with all assignees to a particular + task. {{party_id role_id} {party_id role_id}} + + Todo: dependency changes, deadline changes + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-18 + + @param task_item_id + + @return + + @error +} { + + return [db_list_of_lists get_assignees_roles { }] + +} + + +ad_proc -public pm::task::what_changed { + {-comments_array:required} + {-comments_mime_type_array:required} + {-task_item_id_array:required} + {-number:required} + {-old_one_line_array:required} + {-old_description_array:required} + {-old_description_mime_type_array:required} + {-old_estimated_hours_work_array:required} + {-old_estimated_hours_work_min_array:required} + {-old_estimated_hours_work_max_array:required} + {-old_dependency_array:required} + {-old_percent_complete_array:required} + {-old_end_date_day_array:required} + {-old_end_date_month_array:required} + {-old_end_date_year_array:required} + {-old_project_item_id_array:required} + {-old_assignees_array:required} +} { + Compares how a task was and how it currently is, and + adds to the comments array a list of changes. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-20 + + @param comments_array + + @param comments_mime_type_array + + @param task_item_id_array an array of task_item_ids, with keys + based on number + + @param number the keys to the task_item_id array, a list of integers + + @param old_one_line_array + + @param old_description_array + + @param old_description_mime_type_array + + @param old_estimated_hours_work_array + + @param old_estimated_hours_work_min_array + + @param old_estimated_hours_work_max_array + + @param old_dependency_array + + @param old_percent_complete_array + + @param old_assignees_array + + @return + + @error +} { + + # we will append the changes to these arrays and convert them to + # text/html format + upvar 1 $comments_array comments_arr + upvar 1 $comments_mime_type_array comments_mime_type_arr + + upvar 1 $task_item_id_array task_item_id + upvar 1 $old_one_line_array old_one_line_arr + upvar 1 $old_description_array old_description_arr + upvar 1 $old_description_mime_type_array old_description_mime_type_arr + upvar 1 $old_estimated_hours_work_array old_estimated_hours_work_arr + upvar 1 $old_estimated_hours_work_min_array old_estimated_hours_work_min_arr + upvar 1 $old_estimated_hours_work_max_array old_estimated_hours_work_max_arr + upvar 1 $old_percent_complete_array old_percent_complete_arr + upvar 1 $old_end_date_day_array old_end_date_day_arr + upvar 1 $old_end_date_month_array old_end_date_month_arr + upvar 1 $old_end_date_year_array old_end_date_year_arr + upvar 1 $old_project_item_id_array old_project_item_id_arr + upvar 1 $old_assignees_array old_assignees_arr + upvar 1 $old_dependency_array old_dependency_arr + + set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + + # get the new task values + set tasks_item_id [list] + foreach num $number { + lappend tasks_item_id $task_item_id($num) + } + + pm::task::get \ + -tasks_item_id $tasks_item_id \ + -one_line_array one_line_array \ + -description_array description_array \ + -description_mime_type_array description_mime_type_array \ + -estimated_hours_work_array estimated_hours_work_array \ + -estimated_hours_work_min_array estimated_hours_work_min_array \ + -estimated_hours_work_max_array estimated_hours_work_max_array \ + -dependency_array dependency_array \ + -percent_complete_array percent_complete_array \ + -end_date_day_array end_date_day_array \ + -end_date_month_array end_date_month_array \ + -end_date_year_array end_date_year_array \ + -project_item_id_array project_item_id_array + + + foreach num $number { + + set changes [list] + + set tid $task_item_id($num) + + set old $old_percent_complete_arr($tid) + set new $percent_complete_array($tid) + + if {![string equal $old $new]} { + + if {$new >= 100 && $old < 100} { + + lappend changes "Closing task" + + } elseif {$new < 100 && $old >= 100} { + + lappend changes "Reopening task" + + } else { + lappend changes "Percent complete changed from $old%to $new%" + } + + } + + # end date + if { \ + ![string equal $old_end_date_day_arr($tid) $end_date_day_array($tid)] || \ + ![string equal $old_end_date_month_arr($tid) $end_date_month_array($tid)] || \ + ![string equal $old_end_date_year_arr($tid) $end_date_year_array($tid)]} { + + # internationalize the dates + set iso_date_old "$old_end_date_year_arr($tid)-$old_end_date_month_arr($tid)-$old_end_date_day_arr($tid) 00:00:00" + set iso_date_new "$end_date_year_array($tid)-$end_date_month_array($tid)-$end_date_day_array($tid) 00:00:00" + + if {[string equal $iso_date_old "-- 00:00:00"]} { + set date_old "no hard deadline" + } else { + set date_old [lc_time_fmt $iso_date_old "%x"] + } + + if {[string equal $iso_date_new "-- 00:00:00"]} { + set date_new "no hard deadline" + } else { + set date_new [lc_time_fmt $iso_date_new "%x"] + } + + lappend changes "Hard deadline changed from $date_old to $date_new" + } + + # one_line + if {![string equal $old_one_line_arr($tid) $one_line_array($tid)]} { + lappend changes "Subject changed from $old_one_line_arr($tid) to $one_line_array($tid)" + } + + # description + if { \ + ![string equal $old_description_arr($tid) $description_array($tid)] || \ + ![string equal $old_description_mime_type_arr($tid) $description_mime_type_array($tid)]} { + + set richtext_list [list $old_description_arr($tid) $old_description_mime_type_arr($tid)] + set old_description_html [template::util::richtext::get_property html_value $richtext_list] + set richtext_list [list $description_array($tid) $description_mime_type_array($tid)] + set new_description_html [template::util::richtext::get_property html_value $richtext_list] + + lappend changes "Description changed from
$old_description_html (see below for new description)" + } + + # estimated_hours_work + if {[string is true $use_uncertain_completion_times_p]} { + + if {![string equal $old_estimated_hours_work_min_arr($tid) $estimated_hours_work_min_array($tid)]} { + lappend changes "Work estimate (min) changed from $old_estimated_hours_work_min_arr($tid) to $estimated_hours_work_min_array($tid) hrs" + } + + if {![string equal $old_estimated_hours_work_max_arr($tid) $estimated_hours_work_max_array($tid)]} { + lappend changes "Work estimate (max) changed from $old_estimated_hours_work_max_arr($tid) to $estimated_hours_work_max_array($tid) hrs" + } + } else { + + if {![string equal $old_estimated_hours_work_arr($tid) $estimated_hours_work_array($tid)]} { + lappend changes "Work estimate (min) changed from $old_estimated_hours_work_arr($tid) to $estimated_hours_work_array($tid) hrs" + } + + } + + set new_assignees [pm::task::get_assignee_names \ + -task_item_id $task_item_id($num)] + + # check for assignees that have been added + + foreach new $new_assignees { + if { [lsearch $old_assignees_arr($tid) $new] == -1} { + lappend changes "Added: $new" + } + } + + # check for assignees that have been removed + foreach old $old_assignees_arr($tid) { + if { [lsearch $new_assignees $old] == -1} { + lappend changes "Removed: $old" + } + } + + # project + + if {![string equal $old_project_item_id_arr($tid) $project_item_id_array($tid)]} { + + set old [pm::project::name -project_item_id $old_project_item_id_arr($tid)] + + lappend changes "Project changed from $old" + + } + + # dependency + if {![string equal $old_dependency_arr($tid) $dependency_array($tid)]} { + + if {[empty_string_p $old_dependency_arr($tid)]} { + set old "Nothing" + } else { + set old [pm::task::name \ + -task_item_id $old_dependency_arr($tid)] + } + + if {[empty_string_p $dependency_array($tid)]} { + set new "Nothing" + } else { + set new [pm::task::name \ + -task_item_id $dependency_array($tid)] + } + + lappend changes "Dependency changed from $old ($old_dependency_arr($tid)) to $new ($dependency_array($tid))" + } + + + # convert comments to richtext + set richtext_list [list $comments_arr($num) $comments_mime_type_arr($num)] + set comment_html [template::util::richtext::get_property html_value $richtext_list] + + + # add in changes + + if {[llength $changes] > 0} { + append comment_html "" + + set comments_arr($num) $comment_html + set comments_mime_type_arr($num) "text/html" + } + + } + + +}