* contrib/lisp/ox-taskjuggler.el: Extend variable `complete' to respect clock times if no other information is given.
There are three possibilities for setting a task's progress when exporting to TJ3: 1) If TODO state equals "done" => 100% 2) If property "complete" is explicitly given => use that. 3) Otherwise get the clocksum of the task and set the progress by comparing to `effort'. TINYCHANGE --- contrib/lisp/ox-taskjuggler.el | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/contrib/lisp/ox-taskjuggler.el b/contrib/lisp/ox-taskjuggler.el index 3458e06..a97c075 100644 --- a/contrib/lisp/ox-taskjuggler.el +++ b/contrib/lisp/ox-taskjuggler.el @@ -780,6 +780,16 @@ channel." ;; Closing report. "}\n")) + +(defun org-taskjuggler--clocksum-task (task) +"Return the clocksum of a parsed subtree => does not verify whether the parsed duration matches the start and end times" +(let* ((tsum 0)) + (org-element-map (org-element-contents task) 'clock + (lambda (hl) (setq tsum (+ tsum (org-duration-string-to-minutes (org-element-property :duration hl))))) + ) + tsum +)) + (defun org-taskjuggler--build-task (task info) "Return a task declaration. @@ -791,11 +801,24 @@ a property \"task_id\" it will be used as the id for this task. Otherwise it will use the ID property. If neither is defined a unique id will be associated to it." (let* ((allocate (org-element-property :ALLOCATE task)) + (effort (org-element-property :EFFORT task)) + ;; smart completeness inference: + ;; - if state=done => 100% + ;; - if explicit property for "complete" => take that value + ;; - otherwise get clocksum of this task and relate to the effort, whilst limiting values to [0,99] + ;; => 100% possible if and only if state=DONE. Overbooking does stop at 99%. + (complete-explicit (org-element-property :COMPLETE task)) (complete - (if (eq (org-element-property :todo-type task) 'done) "100" - (org-element-property :COMPLETE task))) + ;; state=done => complete=100 + (if (eq (org-element-property :todo-type task) 'done) 100.0 + ;; else if explicit property => use that + (if complete-explicit (string-to-number complete-explicit) + ;; else guess the completeness from clocksum + (let* ((clocked (org-taskjuggler--clocksum-task task)) + (complete-guess (and effort (/ (* 100 clocked) (org-duration-string-to-minutes effort))))) + (and complete-guess (max (min 99 complete-guess) 0))) ;; check ranges and don't set complete=100 until state=DONE + ))) (depends (org-taskjuggler-resolve-dependencies task info)) - (effort (org-element-property :EFFORT task)) (milestone (or (org-element-property :MILESTONE task) (not (or (org-element-map (org-element-contents task) 'headline @@ -826,7 +849,7 @@ a unique id will be associated to it." (if (>= org-taskjuggler-target-version 3.0) "allocate" "allocations") allocate)) - (and complete (format " complete %s\n" complete)) + (and complete (format " complete %.1f\n" complete)) (and effort (format " effort %s\n" (let* ((minutes (org-duration-string-to-minutes effort)) -- 1.7.9.5