1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 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 500 501 502 503 504 505 506 507 508 509 510 511 512 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 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
|
== The Tutorial: Your first Project ==
We have mentioned already that TaskJuggler uses plain text files that
capture the known parts of the project. As you will see now, the syntax
of these files is easy to understand and very intuitive. This chapter
will walk you step by step through your first project. You create the
project plan for a made-up accounting software project. This project
demonstrates most of the commonly used features of TaskJuggler. It
also includes some of the more advanced concepts that you may or may
not need for your projects. Don't get scared by them. You can use
them once you are more familiar with TaskJuggler and your projects
grow larger. The complete tutorial example comes with your
TaskJuggler software installation. You can use the following command
to find the base directory of the example projects.
ruby -e "puts Gem::Specification.find_by_name('taskjuggler').gem_dir"
The file for the tutorial project is called
''''examples/Tutorial/tutorial.tjp''''. You can use any plain text
editor to view and modify it.
=== Starting the project ===
Every TaskJuggler project file must start with the [[project]]
property. It tells TaskJuggler the name of your project and a start
and end date. The start and end dates don't need to be exact, but must
fit all tasks of the project. It is the time interval the TaskJuggler
scheduler will use to fit the tasks in. So, make it large enough for
all your tasks to fit in. But don't make it too large, because this
will result in longer scheduling times and higher memory consumption.
<[example file="tutorial" tag="header1"]>
All TaskJuggler properties have a unique ID, a name, and a set of
optional attributes. The name must always be specified. The ID can be
omitted if you never have to reference the property from another
context. If you omit the ID, TaskJuggler will automatically generate a
unique ID. The optional attributes are always enclosed in curly
braces. If no optional attributes are specified, the braces can be
omitted as well. In this example we will introduce a number of the
attributes that may or may not matter for your specific projects. If
you don't see an immediate need for a specific attribute, feel free to
ignore it for now. You can always come back to them later. A full list
of the supported project attributes can be found in the ''attributes''
section of the [[project]] property documentation.
Attributes always start with a keyword that identifies them. The
meaning and parameters of attributes depends on the property context
that they are used in. A context is delimited by a set of curly
braces that enclose optional attributes of a property. The area
outside of any property is called the global scope. Usually,
attributes have one or more arguments. These arguments can be dates,
character strings, numbers or symbols. Strings must be enclosed in
single or double quotes. The argument types and meaning is explained
for each keyword in the syntax reference section of this manual.
TaskJuggler manages all events with an accuracy of up to 15 minutes.
In many cases, you don't care about this level of accuracy.
Nevertheless, it's good to have it when you need it. All dates can
optionally be extended by a time. By default, TaskJuggler assumes
that all times are UTC (world time) times. If you prefer a different
time zone, you need to use the [[timezone]] attribute.
<[example file="tutorial" tag="timezone"]>
Be aware that the project start and end dates in the project header
are specified before you specify the time zone. The project header
dates are always assumed to be UTC unless you specify differently.
See [[interval2]] for details.
project acso "Accounting Software" 2002-01-16-0:00-+0100
The [[currency]] attribute specifies the unit of all currency values.
<[example file="tutorial" tag="currency"]>
Because each culture has its own way of specifying dates and numbers,
the format for these is configurable. Use the [[timeformat]]
attribute to specify the default format for dates. This format is used
for reports, it does not affect the way you specify dates in the
project files. Here you always need to use the [[date|TaskJuggler date
notation]].
<[example file="tutorial" tag="formats"]>
We also can specify the way numbers or currency values are shown in
the reports. Use the [[numberformat]] and [[currencyformat]]
attributes for this.
The attribute [[now]] is used to set the current day for the
scheduler to another value than to the moment your invoke TaskJuggler.
If this attribute is not present, TaskJuggler will use the current
moment of time to determine where you are with your tasks. To get a
defined result for the reports in this example we've picked a specific
date that fits our purpose here. In your projects, you would use
[[now]] to generate status reports for the date you specify.
<[example file="tutorial" tag="now"]>
In this tutorial we would like to compare two scenarios of the
project. The first scenario is the one that we have planned. The
second scenario is how it really happened. The two scenarios have the
same task structure, but the start and end dates and other attributes
of the task that are scenario specific may vary. In this example we
assume that the project got delayed and use a second scenario that we
name "Delayed" to describe the actual project. The scenario property
is used to specify the scenarios. The delayed scenario is nested into
the plan scenario. This tells TaskJuggler to use all values from the
plan scenario also for the second scenario unless the second scenario
has it's own values. This is a very easy but also powerful way to
analyze the impact of certain changes to the plan of record. We'll
see further below, how to specify values for a scenario and how to
compare the results.
<[example file="tutorial" tag="scenario"]>
To summarize the above, let's look at the complete header again.
Don't get scared by the wealth of attributes here. They are all
optional and mostly used to illustrate the flexibility of TaskJuggler.
<[example file="tutorial" tag="header2"]>
=== Global Attributes ===
For this tutorial, we also like to do a simple profit and loss
analysis of the project. We will track labor cost versus customer
payments. To calculate the labor costs we have to specify the default
daily costs of an employee. This can be changed for certain employees
later, but it illustrates an important concept of TaskJuggler –
inheritance of attributes. In order to reduce the size of the
TaskJuggler project file to a readable minimum, properties inherit
many attributes from their enclosing scopes. We'll see further below,
what this actually means. Right after the project property we are at
top-level scope, so this is the default for all following properties.
<[example file="tutorial" tag="rate"]>
The [[rate]] attribute can be used to specify the daily costs of
resources. All subsequently declared resources will get this rate. But
it can certainly be changed to a different rate at group or individual
resource level.
You may also want to tell TaskJuggler about holidays that affect
all resources. Global holidays are time periods where TaskJuggler
does not do any resource assignments to tasks.
<[example file="tutorial" tag="vacation"]>
Use the [[leaves]] attribute to define a global holiday. Global
holidays may have a name and must have a date or date range. Other leaves for
individual resources or groups of resources can be defined similarly.
=== Macros ===
Macros are another TaskJuggler feature to save you typing work and to
keep project files small and maintainable. Macros are text patterns
that can be defined once and inserted multiple times in the project
file. A [[macro]] always has a name and the text pattern is enclosed
by square brackets.
<[example file="tutorial" tag="macro"]>
To use the macro you simply have to write
''''${allocate_developers}'''' and TaskJuggler will replace the term
''''${allocate_developers}'''' with the pattern. We will use this
macro further below in the example and then explain the meaning of the
pattern.
=== Declaring Flags ===
A TaskJuggler feature that you will probably make heavy use of is
flags. Once declared you can attach them to any property. When you
generate reports of the TaskJuggler results, you can use the flags to
filter out unwanted properties and limit the report to exactly those
details that you want to have included.
<[example file="tutorial" tag="flags"]>
This is a [[flags]] declaration. All flags need to be declared before
they can be used to avoid hard to find errors due to misspelled flag
names. The flags should be declared before any property at global
scope. We will see further down, how we can make use of these flags.
=== Declaring Accounts ===
The use of our resources will generate costs. For a profit and loss
analysis, we need to balance the cost against the customer payments.
In order not to get lost with all the various amounts, we declare 3
[[account|accounts]] to credit the amounts to. We create one account
for the development costs, one for the documentation costs, and one
for the customer payments.
Actually, there is a fourth account consisting of two accounts nested
into it.
<[example file="tutorial" tag="accounts"]>
The account needs an ID and a name. IDs may only consist of the
characters a to z, A to Z and the underscore. All but the first
character may also be digits 0 to 9. The ID is necessary so that we
can reference the property again later without having to write the
potentially much longer name. The name may contain space characters
and therefore has to be enclosed with single or double quotes.
Accounts can be grouped by nesting them. You can use this feature to
create sets of accounts. Such sets can then be balanced against each
other to create a profit and loss analysis. When you have specified
accounts in your project, you must at least define one default
[[balance]].
<[example file="tutorial" tag="balance"]>
=== Declaring Resources ===
While the above introduced account property is only needed if you
want to do a P&L analysis, resources are usually found in almost any
project.
<[example file="tutorial" tag="resources"]>
This snippet of the example shows the use of the [[resource|
resource property]]. Just like accounts, resources should have an ID
and must have a name. Resource IDs, like account IDs must also be
unique within their property class. As you can see, resource
properties can be nested: ''''dev'''' is a group or container
resource, a team that consists of three other resources.
''''dev1'''', alias Paul Smith, costs more than the normal employee.
So the declaration of ''''dev1'''' overwrites the inherited default
rate with a higher value.
The default value has been inherited from the enclosing scope,
resource ''''dev'''', which in turn has inherited it from the global
scope. The declaration of the resource Klaus Müller uses another
optional attribute. Attributes are only inherited from the parent
property if the attribute was declared in the parent property before
the child property declaration was started.
The syntax reference lists for each property whether an attribute is
inherited from the parent or the attribute in the global scope.
With [[leaves]] you can specify certain time intervals where the
resource is not available. Leaves are list attributes. They accumulate
the declarations. If you want to get rid of inherited or previously
assigned values, you can use the [[purge]] attribute to clear the
list.
''''leaves'''' requires a time interval. It is important to understand
how TaskJuggler handles time intervals. Internally, TaskJuggler uses
the number of seconds after January 1st, 1970 to store any date. So
all dates are actually stored with an accuracy of 1 second in UTC
time. ''''2002-02-01'''' specifies midnight February 1st, 2002.
Following the TaskJuggler concept of requiring as little information
as necessary and extending the rest with sensible defaults,
TaskJuggler adds the time 0:00:00 if nothing else has been specified.
So the vacation ends on midnight February 5th, 2002. Well, almost.
Every time you specify a time interval, the end date is not included
in the interval. So Klaus Müller's vacation ends exactly at 0:00:00 on
February 5th, 2002. February 5 is not part of the leave!
Peter Murphy only works 6.4 hours a day. So we use the
[[limits.resource|limits]] attribute to limit his daily working hours.
We could also define exact working hours using the [[shift|shift
property]], but we ignore this for now.
Note that we have attached the flag ''''team'''' after the declaration
of the sub-resources to the team resources. This way, these flags
don't get passed down to the sub-resources. If we would have declared
the flags before the sub-resources, then they would have the flags
attached as well.
=== Specifying the Tasks ===
Let's focus on the real work now. The project should solve a problem:
the creation of an accounting software. Because the job is quite
complicated, we break it down into several subtasks. We need to do a
specification, develop the software, test the software, and write a
manual. Using the [[task|task property]], this would look as follows:
<[example file="tutorial" tag="task1"]>
Similar to resources, tasks are declared by using the task keyword
followed by an ID and a name string. All TaskJuggler properties have
their own namespaces. This means, that it is quite OK to have a
resource and a task with the same ID. Tasks may have optional
attributes which can be tasks again, so tasks can be nested. In
contrast to all other TaskJuggler properties, task IDs inherit the ID
of the enclosing task as a prefix to the ID. The full ID of the spec
task is AcSo.spec. You need to use this absolute ID when you want to
reference the task later on. This hierarchical name space for tasks
was chosen to support large projects where multiple project managers
may use the same ID in different sub tasks.
To track important milestones of the project, we also added a task
called Milestones. This task, like most of the other tasks will get
some subtasks later on.
We consider the specification task simple enough, so we don't have to
break it into further subtasks. So let's add some more details to it.
<[example file="tutorial" tag="spec"]>
The [[effort]] to complete the task is specified with 20 man-days.
Alternatively we could have used the [[length]] attribute or
the [[duration]] attribute. ''''length'''' specifies the
duration of the task in working days while ''''duration'''' specifies
the duration in calendar days. Contrary to ''''effort'''', these two don't
have to have a specification of the involved resources. Since
''''effort'''' specifies the duration in man-days, we need to say who
should be allocated to the task. The task won't finish before the
resources could be allocated long enough to reach the specified
effort. Tasks with ''''length'''' or ''''duration'''' criteria and
allocated resources will last exactly as long as requested. Resources
will be allocated only if available. It's possible that such a task
ends up with no allocations at all if the resources are always
assigned to other tasks for that period. Each task can only have one
of the three duration criteria. Container tasks may never have a
duration specification. They are automatically adjusted to fit all
sub tasks.
Here we use the allocate_developers macro mentioned above. The
expression ''''${allocate_developers}'''' is simply expanded to
<[example file="tutorial" tag="expandedmacro"]>
If you need to [[allocate]] the same bunch of people to several tasks,
the macro saves you some typing. You could have written the allocate
attributes directly instead of using the macro. Since the allocation
of multiple resources to a task is a good place for macro
usage, we found it a good idea to use it in this example as well.
For TaskJuggler to schedule a task, it needs to know either the start
and end criteria of a task, or one of them and a duration
specification. The start and end criteria can either be fixed dates or
relative dates. Relative dates are specifications of the type ''task B
starts after task A has finished''. Or in other words, task B depends
on task A. In this example the spec task depends on a subtask of the
deliveries task. We have not specified it yet, but it has the local ID
''''start''''.
To specify the dependency between the two tasks, we use the
[[depends]] attribute. This attribute must be followed by one or more
task IDs. If more than one ID is specified, each ID has to be
separated with a comma from the previous one. Task IDs can be either
absolute IDs or relative IDs. An absolute ID of a task is the ID of
this task prepended by the IDs of all enclosing tasks. The task IDs
are separated by a dot from each other. The absolute ID of the
specification task would be ''''AcSo.spec''''.
Relative IDs always start with one or more exclamation marks. Each
exclamation mark moves the scope to the next enclosing task. So
''''!deliveries.start'''' is expanded to ''''AcSo.deliveries.start''''
since ''''AcSo'''' is the enclosing task of ''''deliveries''''. Relative task
IDs are a little bit confusing at first, but have a real advantage
over absolute IDs. Sooner or later you want to move tasks around in
your project and then it's a lot less likely that you have to fix
dependency specifications of relative IDs.
The software development task is still too complex to specify it
directly. So we split it further into subtasks.
<[example file="tutorial" tag="software"]>
We use the [[priority]] attribute to mark the importance of
the tasks. 500 is the default priority of top-level tasks. Setting the
priority to 1000 marks the task as most important task, since the
possible range is 1 (not important at all) to 1000 (ultimately
important). ''''priority'''' is an attribute that is passed down to subtasks
if specified before the subtasks' declaration. So all subtasks of
software have a priority of 1000 as well, unless they have their own
priority definition.
<[example file="tutorial" tag="database"]>
The work on the database coupling should not start before the
specification has been finished. So we again use the [[depends]]
attribute to let TaskJuggler know about this. This time we use two
exclamation marks for the relative ID. The first one puts us in the
scope of the enclosing software task. The second one is to get into
the AcSo scope that contains the spec tasks. For a change, we
[[allocate]] resources directly without using a macro.
<[example file="tutorial" tag="gui"]>
One more interesting thing to note is the fact that we like the
resource ''''dev2'''' only to work 6 hours each day on this task, so
we use the optional attribute [[limits.resource]] to specify this.
TaskJuggler can schedule your project for two different [[scenario|
scenarios]]. We have called the first scenario ''''plan'''' scenario
and the second ''''delayed'''' scenario. Many of the reports allow you
to put the values of both scenarios side by side to each other, so you
can compare the scenarios. All scenario-specific values that are
not explicitly stated for the ''''delayed'''' scenario are taken from
the ''''plan'''' scenario. So the user only has to specify the values
that differ in the delayed scenario. The two scenarios must have the
same task structure and the same dependencies. But the start and end
dates of tasks as well as the duration may vary. In the example we
have planned the work on the graphical user interface to be 35
man-days. It turned out that we actually needed 40 man-days. By
prefixing the [[effort]] attribute with ''''delayed:'''', the
effort value for the ''''delayed'''' scenario can be specified.
<[example file="tutorial" tag="backend"]>
By default, TaskJuggler assumes that all tasks are on schedule.
Sometimes you want to generate reports that show how much of a task
actually has been completed. TaskJuggler uses the current date for
this, unless you have specified another date using the now attribute.
If a task is ahead of schedule or late, this can be specified using
the [[complete]] attribute. This specifies how many percent
of the task have been completed up to the current date. In our case
the back-end implementation is slightly ahead of schedule as we will
see from the report.
<[example file="tutorial" tag="test"]>
The software testing task has been split up into an alpha and
a beta test task. The interesting thing here is, that efforts can not
only be specified as man-days, but also man-weeks, man-hours, etc. By
default, TaskJuggler assumes a man-day is 8 hours, man-week is 40
man-hours or 5 man-days. The conversion factor can be changed using the
[[dailyworkinghours]] attribute.
Let's go back to the outermost task again. At the beginning of the
example we stated that we want to credit all development work to one
account with ID dev and all documentation work to the account doc. To
achieve this, we use the attribute [[chargeset]] to credit
all tasks to the ''''dev'''' account.
For the duration of the ''''AcSo'''' task we also have running costs
for the lease on the building and the equipment. To compensate this,
we charge a daily rate of USD 170 per day using the [[charge]]
attribute.
<[example file="tutorial" tag="charge"]>
Since we specify the attribute for the top-level task before we
declare any subtasks, this attribute will be inherited by all subtasks
and their subtasks and so on. The only exception is the writing of the
manual. We need to change the chargeset for this task again, as it is
also a subtask of AcSo and we want to use a different account for it.
<[example file="tutorial" tag="manual"]>
=== Specifying Milestones ===
All tasks that have been discussed so far, had a certain duration. We
did not always specify the duration explicitly, but we expect them to
last for a certain period of time. Sometimes you just want to capture
a certain moment in your project plan. These moments are usually
called milestones, since they have some level of importance for the
progress of the project.
TaskJuggler has support for milestones as well. Milestones are leaf
tasks that don't have a duration specification.
<[example file="tutorial" tag="deliveries"]>
We have put all important milestones of the project as subtasks of the
deliveries task. This way they show up nicely grouped in the reports.
All milestones either have a dependency or a fixed start date. For the
first milestone we have used the attribute [[start]] to set a fixed start
date. All other tasks have direct or indirect dependencies on this
task. Moving back the start date will slip the whole project. This has
actually happened, so we use the ''''delayed:'''' prefix again to
specify the start date for the delayed scenario.
Every milestone is linked to a customer payment. By using the
[[charge]] attribute we can credit the specified amount to the
account associated with this task. Since we have assigned the
''''rev'''' account to the enclosing task, all milestones will use
this account as well. This time, we use the keyword ''''onstart''''
to indicate that this is not a continuous charge but a one-time
charge that is credited at the begin of the task.
Did you notice the line in the task done that starts with a hash? This
line is commented out. If TaskJuggler finds a hash, it ignores the
rest of the line. This way you can include comments in your project.
The [[maxend]] attribute specifies that the task should end no
later than the specified date. This information is not used for
scheduling, but only for checking the schedule afterwards. Since the
task will end later than the specified date, commenting out the line
would trigger a warning.
Now the project has been completely specified. Stopping here would
result in a valid TaskJuggler file that could be processed and
scheduled. But no reports would be generated to visualize the results.
=== Visualizing the Project ===
To see and share the project data, reports can be generated. You
can generate any number of reports and you can select from a variety
of report types and output formats. To have a report generated after
the project scheduling has been completed, you need include a report
definition into the project description. Report definitions are
properties that are very similar to the task and resource properties
that you are already familiar with. Just like these, report
definitions can be nested to take advantage of the attribute
inheritance mechanism. Every report definition starts with the type
of the report. Each type of report has a particular focus. A
[[taskreport]] lists the project data in the form of a task list.
A [[resourcereport]] does the same in form of a resource list. For a
more generic report, you can use the [[textreport]].
A ''''textreport'''' does not directly present the data in form of a
task or resource list. It just consists of text building blocks that
are described by [[Rich_Text_Attributes|Rich Text]]. There can be a
building block at the top and bottom, as well as three columns in
the center. The column are called ''''left'''', ''''center'''' and
''''right''''.
For our first report, we'll just use the center column for now. Like
every property, you need to specify a name. This name will be the
base name of the generated report file. Depending on the output
format, the proper suffix is appended. For this report, we only chose
to generate a web page in HTML format. There is no default format
defined for reports. If the [[formats]] attribute is not specified,
no output file will be generated for the report specification.
This may seem odd at first glance since TaskJuggler syntax always
tries to use the most compact and readable syntax for the common
case. As you will see in a minute, reports may be composed of several
report specifications. One report specification can include the
output of another report specification as well. In this case, the
included report does not need to generate it's own file. The output
will be included within the output of another report specification.
In case of such composed reports, the output format specification of
the top-level format will be used for all included reports as well.
<[example file="tutorial" tag="overview_report1"]>
For the main report, we choose the file name ''''Overview'''' and the
format ''''html''''. So, the generated file will be called
''''Overview.html''''.
As we've mentioned before, the sections of a ''''textreport'''' are
defined in Rich Text format. Here we use a so called block generator
to include the HTML output of another report definition. The
''''report'''' block generator allows us to compose reports by
combining their output into a single report. You must provide the
''''id'''' parameter to specify which report definition you would
like to use. In this case, it is a report definition with the ID
''''overview''''. Note that generator parameters need to be enclosed
in single or double quotes. We are essentially marking a string
within a string. This can only work out, if we don't use the same
parameter for both. Let's define this report first.
<[example file="tutorial" tag="overview1"]>
Instead of another [[textreport]] definition we are now using a
[[taskreport]]. A task report contains a list of tasks in a table
structure. By default, it contains all tasks of the project. As we
will see later on, we can use filter expressions to limit the content
to a well defined subset of tasks. The table contains a line for each
task and comes by default with a few columns like the name of the
task, and the start and end dates. For this project overview report,
we like to have also the effort for each task, the duration, the
effort, the cost and revenue numbers included. To top it off, we also
include a column with a Gantt chart.
By including the cost and revenue column, we are able to do a simple
profit and loss analysis on the project. This P&L is computed from
the accounts that we have provided above. For this to work, we need
to tell TaskJuggler which accounts are cost accounts and which are
revenue accounts. We have already conveniently grouped the accounts
and the [[balance]] attribute specifies which accounts are used for
the P&L in this report.
<[example file="tutorial" tag="overview2"]>
The columns of the report can be customized. You can overwrite the
default title or the cell content. See [[columns]] for a full list of
available attributes. For the chart column, we'd like to have a
tool tip that displays additional details when the mouse pointer is
placed over a task bar. Since we use this tool tip in several
reports, we have defined the ''''TaskTip'''' macro for it.
<[example file="tutorial" tag="tasktip"]>
The [[tooltip.column|tooltip]] attribute describes the content of the
tool tip. The first parameter is a logical expression that determines
when the tool tip is active. You can specify multiple tool tips. The
first matching one is being displayed. The condition is evaluated for
each report line. The ''''istask()'''' function only evaluates to true
for task lines. See [[functions]] for a complete list of functions
that can be used in [[logicalexpression|logical expressions]].
The content of the tool tip is a template that uses
[[Rich_Text_Attributes#Block_and_Inline_Generators|query
generators]] to include task attributes such as the start and end
date.
We have chosen to include the start and end date of each task in the
report. By default, TaskJuggler lists dates as day, month and year.
We like the format to be similar to the format that the project
syntax uses, but also like to include the weekday. To change the date
format, the [[timeformat]] attribute can be used.
The project will last a few weeks. The most convenient unit to list
efforts in is man or resource days. The [[loadunit]] attribute
tells TaskJuggler to list the load of each task or resource in man
days. Since this will just be a number without a unit, it is
advisable to include a small hint for the reader that these values are
indeed man or resource days. The caption of the table is a convenient
place to put this information by using the [[caption]] attribute.
<[example file="tutorial" tag="overview3"]>
The ''''taskreport'''' can contain more than just the table. It is
not as flexible as the ''''textreport'''', but still has support for
a header and footer. Let's look at the header first. We not only
like to put a headline here, but several paragraphs of text. The
[[header]] attribute is a [[Rich_Text_Attributes|Rich Text]]
attribute just like [[center]]. We could enclose it in single or
double quotes again. But for Strings that span multiple lines and
potentially include single or double quotes as well, scissor-marks or
cut-here-marks are recommended. These marks look like a pair of
scissors that cut along a dashed line. Use
''''<nowiki>-8<-</nowiki>'''' to begin a string and ''''->8-'''' to
terminate it. The opening cut mark must be immediately followed by a
line break. The indentation of the following line defines the
indentation that will be ignored for all lines of the string. The
following lines must have at least the same indentation. The
indentation that exceeds the indentation of the first line will be
kept in the resulting string. With this feature, you can define
multi-line Rich Text strings without disturbing the indentation
structure of your project file.
<[example file="tutorial" tag="overview4"]>
Section headers are surrounded by ''''<nowiki>==</nowiki>''''. The
number of equal signs, define the section level. You need to start
with two equal characters for the first level. Text that is surrounded
by blank lines will create a paragraph. Bullet lists can be made by
starting a line with a ''''#'''' character. Remember that the
indentation of cut-mark strings will be ignored. Your ''''#''''
character must not be the first character in the line as long it is
only preceded by the exact same number of blanks as the first line of
the cut-mark string.
If you want to reference other reports from this report, you can
include the file name of this report by ''''<nowiki>[[</nowiki>''''
and ''''<nowiki>]]</nowiki>''''. Don't include the extension of the
file name, it will be automatically appended. The actual
representation of the reference depends on the chosen output format.
For HTML output, the reference is a click-able link to the referenced
report file.
For the [[footer]] we can proceed accordingly. We just add a few more
paragraphs of text to describe certain aspects of the project. By
putting it all together, we end up with the following report
definition.
<[example file="tutorial" tag="overview"]>
The generated report can be found
[http://www.taskjuggler.org/tj3/examples/Tutorial/Overview.html
here]. It serves as an entry page for the other reports. While it
already contains some references, a navigator bar would be handy as
well. Fortunately, there is a block generator called 'navigator' to
take care of this. But before we can include the navigator in the
report, we need to define it first.
<[example file="tutorial" tag="navigator"]>
[[hidereport]] is a filter attribute. The logical expression
determines which reports will be included in the navigator bar. A
logical expression of 0 means hide no reports, so all are included.
The best place to put a navigator bar in the report is right at the
top. We use two horizontal lines to separate the navigator from the
main headline and the rest of the report.
''''<nowiki>----</nowiki>'''' at the begin of the line create such a
horizontal separation line.
<[example file="tutorial" tag="overview_report2"]>
|