taskjuggler 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (553) hide show
  1. data/CHANGELOG +61 -0
  2. data/README.rdoc +43 -27
  3. data/data/css/tjreport.css +30 -0
  4. data/data/tjp.vim +100 -89
  5. data/examples/ProjectTemplate/template.tjp +338 -0
  6. data/examples/ToDo-List/todolist.tjp +84 -0
  7. data/examples/{tutorial.tjp → Tutorial/tutorial.tjp} +9 -7
  8. data/lib/header.tmpl +1 -1
  9. data/lib/taskjuggler/Account.rb +2 -2
  10. data/lib/taskjuggler/AccountCredit.rb +29 -0
  11. data/lib/taskjuggler/AccountScenario.rb +73 -7
  12. data/lib/taskjuggler/AlertLevelDefinitions.rb +104 -0
  13. data/lib/taskjuggler/AlgorithmDiff.rb +2 -2
  14. data/lib/taskjuggler/Allocation.rb +1 -1
  15. data/lib/taskjuggler/AppConfig.rb +1 -1
  16. data/lib/taskjuggler/AttributeBase.rb +1 -1
  17. data/lib/taskjuggler/AttributeDefinition.rb +1 -1
  18. data/lib/taskjuggler/Attributes.rb +40 -3
  19. data/lib/taskjuggler/BatchProcessor.rb +15 -14
  20. data/lib/taskjuggler/Booking.rb +1 -1
  21. data/lib/taskjuggler/Charge.rb +2 -2
  22. data/lib/taskjuggler/ChargeSet.rb +1 -1
  23. data/lib/taskjuggler/DataCache.rb +24 -12
  24. data/lib/taskjuggler/FileList.rb +1 -1
  25. data/lib/taskjuggler/HTMLDocument.rb +1 -1
  26. data/lib/taskjuggler/HTMLElements.rb +1 -1
  27. data/lib/taskjuggler/ICalendar.rb +1 -1
  28. data/lib/taskjuggler/Interval.rb +1 -1
  29. data/lib/taskjuggler/IntervalList.rb +1 -1
  30. data/lib/taskjuggler/Journal.rb +61 -41
  31. data/lib/taskjuggler/KeywordArray.rb +1 -1
  32. data/lib/taskjuggler/KeywordDocumentation.rb +121 -33
  33. data/lib/taskjuggler/LeaveList.rb +103 -0
  34. data/lib/taskjuggler/Limits.rb +1 -1
  35. data/lib/taskjuggler/Log.rb +6 -3
  36. data/lib/taskjuggler/LogFile.rb +1 -1
  37. data/lib/taskjuggler/LogicalExpression.rb +1 -1
  38. data/lib/taskjuggler/LogicalFunction.rb +16 -2
  39. data/lib/taskjuggler/LogicalOperation.rb +3 -1
  40. data/lib/taskjuggler/MessageHandler.rb +13 -4
  41. data/lib/taskjuggler/PTNProxy.rb +118 -0
  42. data/lib/taskjuggler/Project.rb +58 -67
  43. data/lib/taskjuggler/ProjectFileParser.rb +39 -5
  44. data/lib/taskjuggler/ProjectFileScanner.rb +1 -1
  45. data/lib/taskjuggler/PropertyList.rb +26 -2
  46. data/lib/taskjuggler/PropertySet.rb +8 -1
  47. data/lib/taskjuggler/PropertyTreeNode.rb +36 -32
  48. data/lib/taskjuggler/Query.rb +1 -1
  49. data/lib/taskjuggler/RealFormat.rb +4 -2
  50. data/lib/taskjuggler/Resource.rb +3 -3
  51. data/lib/taskjuggler/ResourceScenario.rb +219 -140
  52. data/lib/taskjuggler/RichText.rb +1 -1
  53. data/lib/taskjuggler/RichText/Document.rb +2 -2
  54. data/lib/taskjuggler/RichText/Element.rb +2 -2
  55. data/lib/taskjuggler/RichText/FunctionExample.rb +2 -2
  56. data/lib/taskjuggler/RichText/FunctionHandler.rb +2 -2
  57. data/lib/taskjuggler/RichText/Parser.rb +2 -2
  58. data/lib/taskjuggler/RichText/RTFHandlers.rb +1 -1
  59. data/lib/taskjuggler/RichText/RTFNavigator.rb +1 -1
  60. data/lib/taskjuggler/RichText/RTFQuery.rb +1 -1
  61. data/lib/taskjuggler/RichText/RTFReport.rb +1 -1
  62. data/lib/taskjuggler/RichText/RTFReportLink.rb +1 -1
  63. data/lib/taskjuggler/RichText/RTFWithQuerySupport.rb +1 -1
  64. data/lib/taskjuggler/RichText/Scanner.rb +18 -4
  65. data/lib/taskjuggler/RichText/Snip.rb +2 -2
  66. data/lib/taskjuggler/RichText/SyntaxRules.rb +6 -14
  67. data/lib/taskjuggler/RichText/TOCEntry.rb +16 -7
  68. data/lib/taskjuggler/RichText/TableOfContents.rb +3 -2
  69. data/lib/taskjuggler/RuntimeConfig.rb +1 -1
  70. data/lib/taskjuggler/Scenario.rb +1 -1
  71. data/lib/taskjuggler/ScenarioData.rb +1 -1
  72. data/lib/taskjuggler/Scoreboard.rb +1 -1
  73. data/lib/taskjuggler/SheetHandlerBase.rb +1 -1
  74. data/lib/taskjuggler/SheetReceiver.rb +1 -1
  75. data/lib/taskjuggler/SheetSender.rb +3 -3
  76. data/lib/taskjuggler/Shift.rb +2 -2
  77. data/lib/taskjuggler/ShiftAssignments.rb +24 -19
  78. data/lib/taskjuggler/ShiftScenario.rb +4 -4
  79. data/lib/taskjuggler/SimpleQueryExpander.rb +1 -1
  80. data/lib/taskjuggler/StatusSheetReceiver.rb +1 -1
  81. data/lib/taskjuggler/StatusSheetSender.rb +1 -1
  82. data/lib/taskjuggler/StdIoWrapper.rb +1 -1
  83. data/lib/taskjuggler/SyntaxReference.rb +5 -2
  84. data/lib/taskjuggler/TableColumnDefinition.rb +1 -1
  85. data/lib/taskjuggler/Task.rb +4 -8
  86. data/lib/taskjuggler/TaskDependency.rb +1 -1
  87. data/lib/taskjuggler/TaskJuggler.rb +1 -1
  88. data/lib/taskjuggler/TaskScenario.rb +131 -51
  89. data/lib/taskjuggler/TernarySearchTree.rb +6 -4
  90. data/lib/taskjuggler/TextFormatter.rb +9 -2
  91. data/lib/taskjuggler/TextParser.rb +13 -3
  92. data/lib/taskjuggler/TextParser/MacroTable.rb +1 -1
  93. data/lib/taskjuggler/TextParser/Pattern.rb +52 -8
  94. data/lib/taskjuggler/TextParser/Rule.rb +11 -5
  95. data/lib/taskjuggler/TextParser/Scanner.rb +1 -1
  96. data/lib/taskjuggler/TextParser/SourceFileInfo.rb +1 -1
  97. data/lib/taskjuggler/TextParser/StackElement.rb +1 -1
  98. data/lib/taskjuggler/TextParser/State.rb +2 -2
  99. data/lib/taskjuggler/TextParser/TokenDoc.rb +1 -1
  100. data/lib/taskjuggler/TimeSheetReceiver.rb +1 -1
  101. data/lib/taskjuggler/TimeSheetSender.rb +1 -1
  102. data/lib/taskjuggler/TimeSheetSummary.rb +1 -1
  103. data/lib/taskjuggler/TimeSheets.rb +4 -6
  104. data/lib/taskjuggler/Tj3AppBase.rb +18 -1
  105. data/lib/taskjuggler/Tj3Config.rb +4 -4
  106. data/lib/taskjuggler/Tj3SheetAppBase.rb +1 -1
  107. data/lib/taskjuggler/TjException.rb +1 -1
  108. data/lib/taskjuggler/TjTime.rb +1 -1
  109. data/lib/taskjuggler/TjpExample.rb +1 -1
  110. data/lib/taskjuggler/TjpSyntaxRules.rb +920 -392
  111. data/lib/taskjuggler/URLParameter.rb +1 -1
  112. data/lib/taskjuggler/UTF8String.rb +1 -1
  113. data/lib/taskjuggler/UserManual.rb +1 -1
  114. data/lib/taskjuggler/VimSyntax.rb +9 -6
  115. data/lib/taskjuggler/WorkingHours.rb +12 -1
  116. data/lib/taskjuggler/XMLDocument.rb +1 -1
  117. data/lib/taskjuggler/XMLElement.rb +1 -1
  118. data/lib/taskjuggler/apps/Tj3.rb +8 -3
  119. data/lib/taskjuggler/apps/Tj3Client.rb +1 -1
  120. data/lib/taskjuggler/apps/Tj3Daemon.rb +1 -1
  121. data/lib/taskjuggler/apps/Tj3Man.rb +1 -1
  122. data/lib/taskjuggler/apps/Tj3SsReceiver.rb +2 -2
  123. data/lib/taskjuggler/apps/Tj3SsSender.rb +1 -1
  124. data/lib/taskjuggler/apps/Tj3TsReceiver.rb +1 -1
  125. data/lib/taskjuggler/apps/Tj3TsSender.rb +1 -1
  126. data/lib/taskjuggler/apps/Tj3TsSummary.rb +1 -1
  127. data/lib/taskjuggler/daemon/Daemon.rb +1 -1
  128. data/lib/taskjuggler/daemon/ProcessIntercom.rb +1 -1
  129. data/lib/taskjuggler/daemon/ProjectBroker.rb +1 -1
  130. data/lib/taskjuggler/daemon/ProjectServer.rb +1 -1
  131. data/lib/taskjuggler/daemon/ReportServer.rb +2 -2
  132. data/lib/taskjuggler/daemon/ReportServlet.rb +1 -1
  133. data/lib/taskjuggler/daemon/WebServer.rb +1 -1
  134. data/lib/taskjuggler/daemon/WelcomePage.rb +1 -1
  135. data/lib/taskjuggler/deep_copy.rb +1 -1
  136. data/lib/taskjuggler/reports/AccountListRE.rb +115 -0
  137. data/lib/taskjuggler/reports/CSVFile.rb +1 -1
  138. data/lib/taskjuggler/reports/CollisionDetector.rb +1 -1
  139. data/lib/taskjuggler/reports/ColumnTable.rb +1 -1
  140. data/lib/taskjuggler/reports/GanttChart.rb +1 -1
  141. data/lib/taskjuggler/reports/GanttContainer.rb +1 -3
  142. data/lib/taskjuggler/reports/GanttHeader.rb +1 -1
  143. data/lib/taskjuggler/reports/GanttHeaderScaleItem.rb +1 -1
  144. data/lib/taskjuggler/reports/GanttLine.rb +23 -12
  145. data/lib/taskjuggler/reports/GanttLoadStack.rb +1 -1
  146. data/lib/taskjuggler/reports/GanttMilestone.rb +1 -1
  147. data/lib/taskjuggler/reports/GanttRouter.rb +1 -1
  148. data/lib/taskjuggler/reports/GanttTaskBar.rb +1 -1
  149. data/lib/taskjuggler/reports/HTMLGraphics.rb +1 -1
  150. data/lib/taskjuggler/reports/ICalReport.rb +5 -2
  151. data/lib/taskjuggler/reports/Navigator.rb +1 -1
  152. data/lib/taskjuggler/reports/NikuReport.rb +1 -1
  153. data/lib/taskjuggler/reports/Report.rb +29 -4
  154. data/lib/taskjuggler/reports/ReportBase.rb +15 -1
  155. data/lib/taskjuggler/reports/ReportContext.rb +1 -1
  156. data/lib/taskjuggler/reports/ReportTable.rb +1 -1
  157. data/lib/taskjuggler/reports/ReportTableCell.rb +1 -1
  158. data/lib/taskjuggler/reports/ReportTableColumn.rb +1 -1
  159. data/lib/taskjuggler/reports/ReportTableLegend.rb +1 -1
  160. data/lib/taskjuggler/reports/ReportTableLine.rb +1 -1
  161. data/lib/taskjuggler/reports/ResourceListRE.rb +3 -5
  162. data/lib/taskjuggler/reports/StatusSheetReport.rb +2 -2
  163. data/lib/taskjuggler/reports/TableReport.rb +336 -204
  164. data/lib/taskjuggler/reports/TableReportColumn.rb +30 -0
  165. data/lib/taskjuggler/reports/TagFile.rb +2 -2
  166. data/lib/taskjuggler/reports/TaskListRE.rb +3 -6
  167. data/lib/taskjuggler/reports/TextReport.rb +1 -1
  168. data/lib/taskjuggler/reports/TimeSheetReport.rb +3 -3
  169. data/lib/taskjuggler/reports/TjpExportRE.rb +4 -1
  170. data/lib/tj3.rb +1 -1
  171. data/lib/tj3client.rb +1 -1
  172. data/lib/tj3d.rb +1 -1
  173. data/lib/tj3man.rb +1 -1
  174. data/lib/tj3ss_receiver.rb +1 -1
  175. data/lib/tj3ss_sender.rb +1 -1
  176. data/lib/tj3ts_receiver.rb +1 -1
  177. data/lib/tj3ts_sender.rb +1 -1
  178. data/lib/tj3ts_summary.rb +1 -1
  179. data/lib/updateheader.sh +4 -1
  180. data/manual/Getting_Started +7 -4
  181. data/manual/How_To_Contribute +26 -5
  182. data/manual/Installation +26 -18
  183. data/manual/Intro +55 -33
  184. data/manual/Reporting_Bugs +18 -8
  185. data/manual/Rich_Text_Attributes +16 -3
  186. data/manual/Software +2 -2
  187. data/manual/TaskJuggler_2x_Migration +2 -2
  188. data/manual/The_TaskJuggler_Syntax +10 -0
  189. data/manual/Tutorial +2 -2
  190. data/manual/html/Day_To_Day_Juggling.html +16 -12
  191. data/manual/html/Getting_Started.html +9 -7
  192. data/manual/html/How_To_Contribute.html +18 -10
  193. data/manual/html/Installation.html +18 -15
  194. data/manual/html/Intro.html +44 -28
  195. data/manual/html/Reporting_Bugs.html +9 -7
  196. data/manual/html/Rich_Text_Attributes.html +11 -8
  197. data/manual/html/Software.html +5 -5
  198. data/manual/html/TaskJuggler_2x_Migration.html +4 -4
  199. data/manual/html/TaskJuggler_Internals.html +3 -3
  200. data/manual/html/The_TaskJuggler_Syntax.html +6 -3
  201. data/manual/html/Tutorial.html +12 -12
  202. data/manual/html/account.html +19 -10
  203. data/manual/html/account.task.html +5 -28
  204. data/manual/html/accountprefix.html +5 -5
  205. data/manual/html/{report.html → accountreport.html} +140 -23
  206. data/manual/html/accountroot.html +142 -0
  207. data/manual/html/active.html +5 -5
  208. data/manual/html/adopt.task.html +7 -8
  209. data/manual/html/aggregate.html +145 -0
  210. data/manual/html/alert.html +12 -11
  211. data/manual/html/alertlevels.html +102 -0
  212. data/manual/html/allocate.html +6 -6
  213. data/manual/html/alphabet.html +1 -1
  214. data/manual/html/alternative.html +3 -3
  215. data/manual/html/author.html +3 -3
  216. data/manual/html/balance.html +84 -11
  217. data/manual/html/booking.resource.html +3 -3
  218. data/manual/html/booking.task.html +3 -3
  219. data/manual/html/caption.html +6 -4
  220. data/manual/html/cellcolor.column.html +3 -3
  221. data/manual/html/celltext.column.html +3 -3
  222. data/manual/html/center.html +28 -4
  223. data/manual/html/charge.html +3 -3
  224. data/manual/html/chargeset.html +5 -5
  225. data/manual/html/columnid.html +40 -9
  226. data/manual/html/columns.html +6 -4
  227. data/manual/html/complete.html +15 -9
  228. data/manual/html/copyright.html +5 -5
  229. data/manual/html/{credit.html → credits.html} +15 -12
  230. data/manual/html/css/tjreport.css +30 -0
  231. data/manual/html/currency.html +28 -15
  232. data/manual/html/currencyformat.html +4 -4
  233. data/manual/html/dailymax.html +3 -3
  234. data/manual/html/dailymin.html +3 -3
  235. data/manual/html/dailyworkinghours.html +3 -3
  236. data/manual/html/date.extend.html +3 -3
  237. data/manual/html/date.html +3 -3
  238. data/manual/html/definitions.html +3 -3
  239. data/manual/html/depends.html +3 -3
  240. data/manual/html/details.html +3 -3
  241. data/manual/html/disabled.html +9 -3
  242. data/manual/html/duration.html +3 -3
  243. data/manual/html/efficiency.html +3 -3
  244. data/manual/html/effort.html +3 -3
  245. data/manual/html/email.html +3 -3
  246. data/manual/html/enabled.html +9 -3
  247. data/manual/html/end.column.html +3 -3
  248. data/manual/html/end.html +3 -3
  249. data/manual/html/end.limit.html +3 -3
  250. data/manual/html/end.report.html +4 -4
  251. data/manual/html/end.timesheet.html +3 -3
  252. data/manual/html/endcredit.html +18 -9
  253. data/manual/html/epilog.html +6 -4
  254. data/manual/html/export.html +10 -6
  255. data/manual/html/extend.html +3 -3
  256. data/manual/html/fail.html +3 -3
  257. data/manual/html/fdl.html +3 -3
  258. data/manual/html/flags.account.html +3 -3
  259. data/manual/html/flags.html +3 -3
  260. data/manual/html/flags.journalentry.html +3 -3
  261. data/manual/html/flags.report.html +6 -4
  262. data/manual/html/flags.resource.html +3 -3
  263. data/manual/html/flags.statussheet.html +3 -3
  264. data/manual/html/flags.task.html +3 -3
  265. data/manual/html/flags.timesheet.html +3 -3
  266. data/manual/html/fontcolor.column.html +3 -3
  267. data/manual/html/footer.html +28 -4
  268. data/manual/html/formats.html +4 -4
  269. data/manual/html/functions.html +4 -4
  270. data/manual/html/gapduration.html +3 -3
  271. data/manual/html/gaplength.html +4 -4
  272. data/manual/html/halign.center.html +3 -3
  273. data/manual/html/halign.column.html +3 -3
  274. data/manual/html/halign.left.html +3 -3
  275. data/manual/html/halign.right.html +3 -3
  276. data/manual/html/hasalert.html +3 -3
  277. data/manual/html/header.html +28 -4
  278. data/manual/html/headline.html +6 -6
  279. data/manual/html/hideaccount.html +73 -0
  280. data/manual/html/hidejournalentry.html +6 -6
  281. data/manual/html/hidereport.html +3 -3
  282. data/manual/html/hideresource.html +4 -4
  283. data/manual/html/hidetask.html +4 -4
  284. data/manual/html/icalreport.html +3 -3
  285. data/manual/html/include.macro.html +4 -4
  286. data/manual/html/include.project.html +5 -6
  287. data/manual/html/include.properties.html +5 -97
  288. data/manual/html/index.html +2 -2
  289. data/manual/html/inherit.extend.html +3 -3
  290. data/manual/html/interval1.html +3 -3
  291. data/manual/html/interval2.html +3 -3
  292. data/manual/html/interval3.html +3 -3
  293. data/manual/html/interval4.html +3 -3
  294. data/manual/html/isactive.html +3 -3
  295. data/manual/html/ischildof.html +3 -3
  296. data/manual/html/isdependencyof.html +3 -3
  297. data/manual/html/isdutyof.html +3 -3
  298. data/manual/html/isfeatureof.html +3 -3
  299. data/manual/html/isleaf.html +3 -3
  300. data/manual/html/ismilestone.html +3 -3
  301. data/manual/html/isongoing.html +3 -3
  302. data/manual/html/isresource.html +5 -5
  303. data/manual/html/{alert level.html → isresponsibilityof.html} +19 -14
  304. data/manual/html/istask.html +5 -5
  305. data/manual/html/journalattributes.html +6 -4
  306. data/manual/html/journalentry.html +3 -3
  307. data/manual/html/journalmode.html +8 -6
  308. data/manual/html/leaveallowance.html +139 -0
  309. data/manual/html/leaves.html +140 -0
  310. data/manual/html/left.html +30 -6
  311. data/manual/html/length.html +4 -4
  312. data/manual/html/limits.allocate.html +5 -32
  313. data/manual/html/limits.html +3 -3
  314. data/manual/html/limits.resource.html +3 -3
  315. data/manual/html/limits.task.html +3 -3
  316. data/manual/html/listitem.column.html +3 -3
  317. data/manual/html/listtype.column.html +3 -3
  318. data/manual/html/loadunit.html +6 -4
  319. data/manual/html/logicalexpression.html +3 -3
  320. data/manual/html/logicalflagexpression.html +3 -3
  321. data/manual/html/macro.html +3 -3
  322. data/manual/html/managers.html +3 -3
  323. data/manual/html/mandatory.html +3 -3
  324. data/manual/html/maxend.html +3 -3
  325. data/manual/html/maximum.html +3 -3
  326. data/manual/html/maxstart.html +3 -3
  327. data/manual/html/milestone.html +3 -3
  328. data/manual/html/minend.html +3 -3
  329. data/manual/html/minimum.html +3 -3
  330. data/manual/html/minstart.html +3 -3
  331. data/manual/html/monthlymax.html +3 -3
  332. data/manual/html/monthlymin.html +3 -3
  333. data/manual/html/navbar.html +23 -5
  334. data/manual/html/navigator.html +34 -3
  335. data/manual/html/newtask.html +3 -3
  336. data/manual/html/nikureport.html +3 -3
  337. data/manual/html/note.task.html +3 -3
  338. data/manual/html/now.html +3 -3
  339. data/manual/html/numberformat.html +4 -4
  340. data/manual/html/onend.html +3 -3
  341. data/manual/html/onstart.html +3 -3
  342. data/manual/html/opennodes.html +6 -4
  343. data/manual/html/overtime.booking.html +4 -4
  344. data/manual/html/period.column.html +3 -3
  345. data/manual/html/period.limit.html +3 -3
  346. data/manual/html/period.report.html +4 -4
  347. data/manual/html/period.task.html +3 -3
  348. data/manual/html/persistent.html +3 -3
  349. data/manual/html/precedes.html +3 -3
  350. data/manual/html/priority.html +3 -3
  351. data/manual/html/priority.timesheet.html +3 -3
  352. data/manual/html/project.html +4 -4
  353. data/manual/html/projectid.html +3 -3
  354. data/manual/html/projectid.task.html +3 -3
  355. data/manual/html/projectids.html +3 -3
  356. data/manual/html/projection.html +9 -3
  357. data/manual/html/prolog.html +6 -4
  358. data/manual/html/properties.html +193 -9
  359. data/manual/html/purge.html +5 -5
  360. data/manual/html/rate.html +3 -3
  361. data/manual/html/rate.resource.html +3 -3
  362. data/manual/html/reference.extend.html +3 -3
  363. data/manual/html/remaining.html +3 -3
  364. data/manual/html/replace.html +9 -6
  365. data/manual/html/reportprefix.html +5 -5
  366. data/manual/html/resource.html +22 -4
  367. data/manual/html/resourceattributes.html +6 -6
  368. data/manual/html/resourceprefix.html +3 -3
  369. data/manual/html/resourcereport.html +311 -8
  370. data/manual/html/resourceroot.html +6 -4
  371. data/manual/html/resources.limit.html +4 -4
  372. data/manual/html/responsible.html +3 -3
  373. data/manual/html/richtext.extend.html +3 -3
  374. data/manual/html/right.html +30 -6
  375. data/manual/html/rollupaccount.html +69 -0
  376. data/manual/html/rollupresource.html +6 -6
  377. data/manual/html/rolluptask.html +4 -4
  378. data/manual/html/scale.column.html +3 -3
  379. data/manual/html/scenario.html +3 -3
  380. data/manual/html/scenario.ical.html +3 -3
  381. data/manual/html/scenarios.export.html +3 -3
  382. data/manual/html/scenarios.html +6 -4
  383. data/manual/html/scenariospecific.extend.html +3 -3
  384. data/manual/html/scheduled.html +3 -3
  385. data/manual/html/scheduling.html +3 -3
  386. data/manual/html/select.html +3 -3
  387. data/manual/html/selfcontained.html +6 -4
  388. data/manual/html/shift.allocate.html +77 -0
  389. data/manual/html/shift.html +13 -7
  390. data/manual/html/shift.resource.html +11 -5
  391. data/manual/html/shift.task.html +9 -3
  392. data/manual/html/shift.timesheet.html +4 -4
  393. data/manual/html/shifts.allocate.html +6 -6
  394. data/manual/html/shifts.resource.html +3 -3
  395. data/manual/html/shifts.task.html +3 -3
  396. data/manual/html/shorttimeformat.html +3 -3
  397. data/manual/html/sloppy.booking.html +4 -4
  398. data/manual/html/sloppy.projection.html +12 -6
  399. data/manual/html/sortaccounts.html +73 -0
  400. data/manual/html/sortjournalentries.html +8 -6
  401. data/manual/html/sortresources.html +4 -4
  402. data/manual/html/sorttasks.html +4 -4
  403. data/manual/html/start.column.html +3 -3
  404. data/manual/html/start.html +3 -3
  405. data/manual/html/start.limit.html +3 -3
  406. data/manual/html/start.report.html +4 -4
  407. data/manual/html/startcredit.html +10 -4
  408. data/manual/html/status.statussheet.html +5 -5
  409. data/manual/html/status.timesheet.html +5 -5
  410. data/manual/html/statussheet.html +3 -3
  411. data/manual/html/statussheetreport.html +10 -6
  412. data/manual/html/strict.projection.html +10 -4
  413. data/manual/html/summary.html +3 -3
  414. data/manual/html/supplement.html +5 -5
  415. data/manual/html/supplement.resource.html +22 -4
  416. data/manual/html/supplement.task.html +4 -4
  417. data/manual/html/tagfile.html +3 -3
  418. data/manual/html/task.html +3 -3
  419. data/manual/html/task.statussheet.html +3 -3
  420. data/manual/html/task.timesheet.html +3 -3
  421. data/manual/html/taskattributes.html +3 -3
  422. data/manual/html/taskprefix.html +3 -3
  423. data/manual/html/taskreport.html +347 -8
  424. data/manual/html/taskroot.html +6 -4
  425. data/manual/html/text.extend.html +3 -3
  426. data/manual/html/textreport.html +333 -8
  427. data/manual/html/timeformat.html +4 -4
  428. data/manual/html/timeoff.nikureport.html +3 -3
  429. data/manual/html/timesheet.html +3 -3
  430. data/manual/html/timesheetreport.html +10 -6
  431. data/manual/html/timezone.export.html +3 -3
  432. data/manual/html/timezone.html +3 -3
  433. data/manual/html/timezone.report.html +6 -4
  434. data/manual/html/timezone.shift.html +3 -3
  435. data/manual/html/timingresolution.html +3 -3
  436. data/manual/html/title.column.html +3 -3
  437. data/manual/html/title.html +4 -4
  438. data/manual/html/toc.html +1705 -658
  439. data/manual/html/tooltip.column.html +3 -3
  440. data/manual/html/trackingscenario.html +3 -3
  441. data/manual/html/treelevel.html +3 -3
  442. data/manual/html/vacation.html +3 -3
  443. data/manual/html/vacation.resource.html +4 -4
  444. data/manual/html/vacation.shift.html +4 -4
  445. data/manual/html/warn.html +3 -3
  446. data/manual/html/weeklymax.html +3 -3
  447. data/manual/html/weeklymin.html +3 -3
  448. data/manual/html/weekstartsmonday.html +3 -3
  449. data/manual/html/weekstartssunday.html +3 -3
  450. data/manual/html/width.column.html +3 -3
  451. data/manual/html/work.html +3 -3
  452. data/manual/html/workinghours.project.html +3 -3
  453. data/manual/html/workinghours.resource.html +3 -3
  454. data/manual/html/workinghours.shift.html +3 -3
  455. data/manual/html/yearlyworkingdays.html +4 -4
  456. data/spec/ICalendar_spec.rb +4 -2
  457. data/spec/IntervalList_spec.rb +1 -1
  458. data/spec/ProjectBroker_spec.rb +2 -6
  459. data/spec/StatusSheets_spec.rb +1 -1
  460. data/spec/TernarySearchTree_spec.rb +2 -2
  461. data/spec/TimeSheets_spec.rb +1 -1
  462. data/spec/Tj3Daemon_spec.rb +1 -1
  463. data/spec/Tj3_spec.rb +1 -1
  464. data/spec/support/DaemonControl.rb +1 -1
  465. data/spec/support/spec_helper.rb +19 -0
  466. data/taskjuggler.gemspec +1 -0
  467. data/test/MessageChecker.rb +1 -1
  468. data/test/ReferenceGenerator.rb +1 -1
  469. data/test/TestSuite/CSV-Reports/Leave.tjp +37 -0
  470. data/test/TestSuite/CSV-Reports/celltext.tjp +1 -1
  471. data/test/TestSuite/CSV-Reports/efficiency.tjp +20 -0
  472. data/test/TestSuite/CSV-Reports/headcount.tjp +31 -0
  473. data/test/TestSuite/CSV-Reports/refs/Leave.csv +5 -0
  474. data/test/TestSuite/CSV-Reports/refs/alert.csv +6 -0
  475. data/test/TestSuite/CSV-Reports/refs/celltext.csv +6 -0
  476. data/test/TestSuite/CSV-Reports/refs/efficiency.csv +5 -0
  477. data/test/TestSuite/CSV-Reports/refs/headcount.csv +4 -0
  478. data/test/TestSuite/CSV-Reports/refs/sortByTree.csv +6 -0
  479. data/test/TestSuite/CSV-Reports/refs/sortBy_duration.down.csv +6 -0
  480. data/test/TestSuite/CSV-Reports/refs/sortBy_effort.up.csv +6 -0
  481. data/test/TestSuite/CSV-Reports/refs/sortBy_plan.start.down.csv +6 -0
  482. data/test/TestSuite/CSV-Reports/refs/taskreport.csv +6 -0
  483. data/test/TestSuite/CSV-Reports/refs/taskreport_with_resources.csv +14 -0
  484. data/test/TestSuite/CSV-Reports/resourcereport.tjp +1 -1
  485. data/test/TestSuite/CSV-Reports/resourcereport_with_tasks.tjp +1 -1
  486. data/test/TestSuite/CSV-Reports/sortByTree.tjp +1 -1
  487. data/test/TestSuite/CSV-Reports/sortBy_plan.start.down.tjp +1 -1
  488. data/test/TestSuite/CSV-Reports/taskreport.tjp +1 -1
  489. data/test/TestSuite/CSV-Reports/taskreport_with_resources.tjp +1 -1
  490. data/test/TestSuite/Export-Reports/refs/AccountReport.tjp +1089 -0
  491. data/test/TestSuite/Export-Reports/refs/AlertLevels.tjp +24 -0
  492. data/test/TestSuite/Export-Reports/refs/Complete.tjp +5 -25
  493. data/test/TestSuite/Export-Reports/refs/navigator.tjp +58 -0
  494. data/test/TestSuite/Export-Reports/refs/template.tjp +142 -0
  495. data/test/TestSuite/Export-Reports/refs/textreport.tjp +19 -0
  496. data/test/TestSuite/ReportGenerator/Correct/Alerts.tjp +26 -7
  497. data/test/TestSuite/ReportGenerator/Correct/refs/Alerts-1.csv +177 -141
  498. data/test/TestSuite/ReportGenerator/Correct/refs/FTE-1.csv +1 -1
  499. data/test/TestSuite/Scheduler/Correct/Allocate.tjp +2 -2
  500. data/test/TestSuite/Scheduler/Correct/Shift2.tjp +4 -4
  501. data/test/TestSuite/Syntax/Correct/Account.tjp +23 -10
  502. data/test/TestSuite/Syntax/Correct/AccountReport.tjp +74 -0
  503. data/test/TestSuite/Syntax/Correct/AdoptedTasks.tjp +4 -0
  504. data/test/TestSuite/Syntax/Correct/AlertLevels.tjp +25 -0
  505. data/test/TestSuite/Syntax/Correct/Celltext.tjp +3 -3
  506. data/test/TestSuite/Syntax/Correct/Complete.tjp +8 -5
  507. data/test/TestSuite/Syntax/Correct/Leave.tjp +37 -0
  508. data/test/TestSuite/Syntax/Correct/Reports.tjp +4 -4
  509. data/test/TestSuite/Syntax/Correct/Shift.tjp +4 -4
  510. data/test/TestSuite/Syntax/Correct/manual2example.rb +4 -3
  511. data/test/TestSuite/Syntax/Correct/navigator.tjp +31 -0
  512. data/test/TestSuite/Syntax/Correct/template.tjp +338 -0
  513. data/test/TestSuite/Syntax/Correct/textreport.tjp +21 -0
  514. data/test/TestSuite/Syntax/Correct/tutorial.tjp +12 -10
  515. data/test/TestSuite/Syntax/Errors/{adopt_duplicate_child.tjp → adopt_duplicate_child-1.tjp} +0 -0
  516. data/test/TestSuite/Syntax/Errors/{adopt_common_root.tjp → adopt_duplicate_child-2.tjp} +1 -1
  517. data/test/TestSuite/Syntax/Errors/{adopt_duplicate_parent.tjp → adopt_duplicate_child-3.tjp} +1 -1
  518. data/test/TestSuite/Syntax/Errors/adopt_self.tjp +7 -0
  519. data/test/TestSuite/Syntax/Errors/alert_level_redef.tjp +8 -0
  520. data/test/TestSuite/Syntax/Errors/alert_name_redef.tjp +8 -0
  521. data/test/TestSuite/Syntax/Errors/too_few_alert_levels.tjp +5 -0
  522. data/test/TjpGen.rb +1 -1
  523. data/test/all.rb +1 -1
  524. data/test/test_AlgorithmDiff.rb +1 -1
  525. data/test/test_BatchProcessor.rb +23 -10
  526. data/test/test_CSV-Reports.rb +1 -1
  527. data/test/test_CSVFile.rb +1 -1
  528. data/test/test_CollisionDetector.rb +1 -1
  529. data/test/test_Export-Reports.rb +1 -1
  530. data/test/test_Journal.rb +42 -15
  531. data/test/test_Limits.rb +1 -1
  532. data/test/test_LogicalExpression.rb +1 -1
  533. data/test/test_MacroTable.rb +8 -3
  534. data/test/test_Project.rb +1 -1
  535. data/test/test_ProjectFileScanner.rb +1 -1
  536. data/test/test_PropertySet.rb +1 -1
  537. data/test/test_Query.rb +1 -1
  538. data/test/test_RealFormat.rb +1 -1
  539. data/test/test_ReportGenerator.rb +1 -1
  540. data/test/test_RichText.rb +1 -1
  541. data/test/test_Scheduler.rb +1 -1
  542. data/test/test_ShiftAssignments.rb +1 -1
  543. data/test/test_SimpleQueryExpander.rb +1 -1
  544. data/test/test_Syntax.rb +1 -1
  545. data/test/test_TextFormatter.rb +1 -1
  546. data/test/test_TjTime.rb +1 -1
  547. data/test/test_TjpExample.rb +1 -1
  548. data/test/test_URLParameter.rb +1 -1
  549. data/test/test_UTF8String.rb +1 -1
  550. data/test/test_WorkingHours.rb +1 -1
  551. data/test/test_deep_copy.rb +1 -1
  552. metadata +318 -248
  553. data/test/TestSuite/Syntax/Errors/purge_no_list.tjp +0 -8
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = TjException.rb -- The TaskJuggler III Project Management Software
5
5
  #
6
- # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
7
7
  # by Chris Schlaeger <chris@linux.com>
8
8
  #
9
9
  # This program is free software; you can redistribute it and/or modify
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = TjTime.rb -- The TaskJuggler III Project Management Software
5
5
  #
6
- # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
7
7
  # by Chris Schlaeger <chris@linux.com>
8
8
  #
9
9
  # This program is free software; you can redistribute it and/or modify
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = TjpExample.rb -- The TaskJuggler III Project Management Software
5
5
  #
6
- # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
7
7
  # by Chris Schlaeger <chris@linux.com>
8
8
  #
9
9
  # This program is free software; you can redistribute it and/or modify
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = TjpSyntaxRules.rb -- The TaskJuggler III Project Management Software
5
5
  #
6
- # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
7
7
  # by Chris Schlaeger <chris@linux.com>
8
8
  #
9
9
  # This program is free software; you can redistribute it and/or modify
@@ -61,6 +61,18 @@ EOT
61
61
  optionsRule('accountAttributes')
62
62
  end
63
63
 
64
+ def rule_accountCredit
65
+ pattern(%w( !valDate $STRING !number ), lambda {
66
+ AccountCredit.new(@val[0], @val[1], @val[2])
67
+ })
68
+ arg(1, 'description', 'Short description of the transaction')
69
+ arg(2, 'amount', 'Amount to be booked.')
70
+ end
71
+
72
+ def rule_accountCredits
73
+ listRule('moreAccountCredits', '!accountCredit')
74
+ end
75
+
64
76
  def rule_accountHeader
65
77
  pattern(%w( _account !optionalID $STRING ), lambda {
66
78
  if @property.nil? && !@accountprefix.empty?
@@ -91,18 +103,78 @@ EOT
91
103
  })
92
104
  end
93
105
 
106
+ def rule_accountReport
107
+ pattern(%w( !accountReportHeader !reportBody ), lambda {
108
+ @property = @property.parent
109
+ })
110
+ level(:beta)
111
+ doc('accountreport', <<'EOT'
112
+ The report lists accounts and their respective values in a table. The report can operate in two modes:
113
+
114
+ # Balance mode: If a [[balance]] has been set, the report will include the
115
+ defined cost and revenue accounts as well as all their sub accounts. To reduce
116
+ the list of included accounts, you can use the [[hideaccount]],
117
+ [[rollupaccount]] or [[accountroot]] attributes. The order of the task can
118
+ be controlled with [[sortaccounts]]. If the first sorting criteria is tree
119
+ sorting, the parent accounts will always be included to form the tree.
120
+ Tree sorting is the default. You need to change it if you do not want certain
121
+ parent accounts to be included in the report. Additionally, it will contain a line at the end that lists the balance (revenue - cost).
122
+
123
+ # Normal mode: All reports are listed in the order and completeness as defined
124
+ by the other report attributes. No balance line will be included.
125
+ EOT
126
+ )
127
+ example('AccountReport')
128
+ end
129
+
130
+ def rule_accountReportHeader
131
+ pattern(%w( _accountreport !optionalID !reportName ), lambda {
132
+ newReport(@val[1], @val[2], :accountreport, @sourceFileInfo[0])
133
+
134
+ unless @property.modified?('columns')
135
+ # Set the default columns for this report.
136
+ %w( bsi name monthly ).each do |col|
137
+ @property.get('columns') <<
138
+ TableColumnDefinition.new(col, columnTitle(col))
139
+ end
140
+ end
141
+ # Show all accounts, sorted by tree, seqno-up.
142
+ unless @property.modified?('hideAccount')
143
+ @property.set('hideAccount',
144
+ LogicalExpression.new(LogicalOperation.new(0)))
145
+ end
146
+ unless @property.modified?('sortAccounts')
147
+ @property.set('sortAccounts',
148
+ [ [ 'tree', true, -1 ],
149
+ [ 'seqno', true, -1 ] ])
150
+ end
151
+ })
152
+ end
153
+
94
154
  def rule_accountScenarioAttributes
95
- pattern(%w( _credit !valDate $STRING !number ), lambda {
96
- #@property['credit', @scenarioIdx] +=
97
- # AccountCredit.new(@val[1], @val[2], @val[3])
155
+ pattern(%w( _aggregate !aggregate ), lambda {
156
+ @property.set('aggregate', @val[1])
157
+ })
158
+ doc('aggregate', <<'EOT'
159
+ Specifies whether the account is used to track task or resource specific
160
+ amounts. The default is to track tasks.
161
+ EOT
162
+ )
163
+ example('AccountReport')
164
+
165
+ pattern(%w( _credits !accountCredits ), lambda {
166
+ begin
167
+ @property['credits', @scenarioIdx] += @val[1]
168
+ rescue AttributeOverwrite
169
+ # Adding multiple credits for an account is a pretty common idiom.
170
+ end
98
171
  })
99
- doc('credit', <<'EOT'
100
- Book the specified amount to the account at the specified date.
172
+ doc('credits', <<'EOT'
173
+ Book the specified amounts to the account at the specified date. The
174
+ desciptions are just used for documentary purposes.
101
175
  EOT
102
176
  )
103
177
  example('Account', '1')
104
- arg(2, 'description', 'Short description of the transaction')
105
- arg(3, 'amount', 'Amount to be booked.')
106
178
 
107
179
  pattern(%w( !flags ))
108
180
  doc('flags.account', <<'EOT'
@@ -114,28 +186,48 @@ EOT
114
186
  # Other attributes will be added automatically.
115
187
  end
116
188
 
189
+ def rule_aggregate
190
+ pattern(%w( _resources ), lambda {
191
+ :resources
192
+ })
193
+ descr('Aggregate resources')
194
+
195
+ pattern(%w( _tasks ), lambda {
196
+ :tasks
197
+ })
198
+ descr('Aggregate tasks')
199
+ end
200
+
117
201
  def rule_alertLevel
118
202
  pattern(%w( $ID ), lambda {
119
- level = @project.alertLevelIndex(@val[0])
203
+ level = @project['alertLevels'].indexById(@val[0])
120
204
  unless level
121
- error('bad_alert', "Unknown alert level #{@val[1]}. Must be " +
122
- 'green, yellow or red', @sourceFileInfo[0])
205
+ levels = @project['alertLevels'].map { |l| l.id }
206
+ error('bad_alert', "Unknown alert level #{@val[0]}. Must be " +
207
+ "one of #{levels.join(', ')}", @sourceFileInfo[0])
123
208
  end
124
209
  level
125
210
  })
126
- doc('alert level', <<'EOT'
127
- Specify the alert level for this entry. Supported values are green, yellow and
128
- red. The default value is green. This attribute is inteded to be used for
129
- status reporting. When used for a journal entry that is associated with a
130
- property, the value can be reported in the alert column. When multiple entries
131
- have been specified for the property, the entry with the date closest to the
132
- report end date will be used. Container properties will inherit the highest
133
- alert level of all its sub properties unless it has an own journal entry dated
134
- closer to the report end than all of its sub properties.
211
+ arg(0, 'alert level', <<'EOT'
212
+ By default supported values are ''''green'''', ''''yellow'''' and ''''red''''.
213
+ The default value is ''''green''''. You can define your own levels with
214
+ [[alertlevels]].
135
215
  EOT
136
216
  )
137
217
  end
138
218
 
219
+ def rule_alertLevelDefinition
220
+ pattern(%w( $ID $STRING !color ), lambda {
221
+ [ @val[0], @val[1], @val[2] ]
222
+ })
223
+ arg(0, 'ID', "A unique ID for the alert level")
224
+ arg(1, 'color name', 'A unique name of the alert level color')
225
+ end
226
+
227
+ def rule_alertLevelDefinitions
228
+ listRule('moreAlertLevelDefinitions', '!alertLevelDefinition')
229
+ end
230
+
139
231
  def rule_allocate
140
232
  pattern(%w( _allocate !allocations ), lambda {
141
233
  checkContainer('allocate')
@@ -192,7 +284,8 @@ EOT
192
284
  end
193
285
  end
194
286
  })
195
- doc('limits.allocate', 'This keyword is deprecated. Don\'t use it anymore!')
287
+ level(:removed)
288
+ doc('limits.allocate', '')
196
289
 
197
290
  pattern(%w( _select !allocationSelectionMode ), lambda {
198
291
  @allocate.setSelectionMode(@val[1])
@@ -230,7 +323,38 @@ So either all mandatory resources can be allocated for the time slot, or no
230
323
  resource will be allocated.
231
324
  EOT
232
325
  )
233
- pattern(%w( _shift !allocationShiftAssignment ))
326
+ pattern(%w( !allocateShiftAssignments !shiftAssignment ), lambda {
327
+ begin
328
+ @allocate.shifts = @shiftAssignments
329
+ rescue AttributeOverwrite
330
+ # Multiple shift assignments are a common idiom, so don't warn about
331
+ # them.
332
+ end
333
+ @shiftAssignments = nil
334
+ })
335
+ level(:deprecated)
336
+ also('shifts.allocate')
337
+ doc('shift.allocate', <<'EOT'
338
+ Limits the allocations of resources during the specified interval to the
339
+ specified shift. Multiple shifts can be defined, but shift intervals may not
340
+ overlap. Allocation shifts are an additional restriction to the
341
+ [[shifts.task|task shifts]] and [[shifts.resource|resource shifts]] or
342
+ [[workinghours.resource|resource working hours]]. Allocations will only be
343
+ made for time slots that are specified as duty time in all relevant shifts.
344
+ The restriction to the shift is only active during the specified time
345
+ interval. Outside of this interval, no restrictions apply.
346
+ EOT
347
+ )
348
+
349
+ pattern(%w( !allocateShiftsAssignments !shiftAssignments ), lambda {
350
+ begin
351
+ @allocate.shifts = @shiftAssignments
352
+ rescue AttributeOverwrite
353
+ # Multiple shift assignments are a common idiom, so don't warn about
354
+ # them.
355
+ end
356
+ @shiftAssignments = nil
357
+ })
234
358
  doc('shifts.allocate', <<'EOT'
235
359
  Limits the allocations of resources during the specified interval to the
236
360
  specified shift. Multiple shifts can be defined, but shift intervals may not
@@ -280,27 +404,15 @@ EOT
280
404
  descr('Pick a random resource from the list.')
281
405
  end
282
406
 
283
- def rule_allocationShiftAssignment
284
- pattern(%w( !shiftId !intervalsOptional ), lambda {
285
- # Make sure we have a ShiftAssignment for the allocation.
286
- if @allocate.shifts.nil?
287
- @allocate.shifts = ShiftAssignments.new
288
- @allocate.shifts.project = @project
289
- end
407
+ def rule_allocateShiftAssignments
408
+ pattern(%w( _shift ), lambda {
409
+ @shiftAssignments = @allocate.shifts
410
+ })
411
+ end
290
412
 
291
- if @val[1].nil?
292
- intervals = [ TimeInterval.new(@project['start'], @project['end']) ]
293
- else
294
- intervals = @val[1]
295
- end
296
- intervals.each do |interval|
297
- if !@allocate.shifts.
298
- addAssignment(ShiftAssignment.new(@val[0].scenario(@scenarioIdx),
299
- interval))
300
- error('shift_assignment_overlap',
301
- 'Shifts may not overlap each other.', @sourceFileInfo[0])
302
- end
303
- end
413
+ def rule_allocateShiftsAssignments
414
+ pattern(%w( _shifts ), lambda {
415
+ @shiftAssignments = @allocate.shifts
304
416
  })
305
417
  end
306
418
 
@@ -338,29 +450,38 @@ EOT
338
450
  end
339
451
 
340
452
  def rule_balance
341
- pattern(%w( _balance !accountId !accountId ), lambda {
342
- if @val[1].parent
453
+ pattern(%w( _balance !balanceAccounts ), lambda {
454
+ @val[1]
455
+ })
456
+ doc('balance', <<'EOT'
457
+ During report generation, TaskJuggler can consider some accounts to be revenue accounts, while other can be considered cost accounts. By using the balance attribute, two top-level accounts can be designated for a profit-loss-analysis. This analysis includes all sub accounts of these two top-level accounts.
458
+
459
+ To clear a previously set balance, just use a ''''-''''.
460
+ EOT
461
+ )
462
+ example('AccountReport')
463
+ end
464
+
465
+ def rule_balanceAccounts
466
+ pattern(%w( !accountId !accountId ), lambda {
467
+ if @val[0].parent
343
468
  error('cost_acct_no_top',
344
- "The cost account #{@val[1].fullId} is not a top-level account.",
345
- @sourceFileInfo[1])
469
+ "The cost account #{@val[0].fullId} is not a top-level account.",
470
+ @sourceFileInfo[0])
346
471
  end
347
- if @val[2].parent
472
+ if @val[1].parent
348
473
  error('rev_acct_no_top',
349
- "The revenue account #{@val[2].fullId} is not a top-level " +
350
- "account.", @sourceFileInfo[2])
474
+ "The revenue account #{@val[1].fullId} is not a top-level " +
475
+ "account.", @sourceFileInfo[1])
351
476
  end
352
- if @val[1] == @val[2]
477
+ if @val[0] == @val[1]
353
478
  error('cost_rev_same',
354
479
  'The cost and revenue accounts may not be the same.',
355
- @sourceFileInfo[1])
480
+ @sourceFileInfo[0])
356
481
  end
357
- [ @val[1], @val[2] ]
482
+ [ @val[0], @val[1] ]
358
483
  })
359
- doc('balance', <<'EOT'
360
- During report generation, TaskJuggler can consider some accounts to be revenue accounts, while other can be considered cost accounts. By using the balance attribute, two top-level accounts can be designated for a profit-loss-analysis. This analysis includes all sub accounts of these two top-level accounts.
361
- EOT
362
- )
363
- arg(1, 'cost account', <<'EOT'
484
+ arg(0, 'cost account', <<'EOT'
364
485
  The top-level account that is used for all cost related charges.
365
486
  EOT
366
487
  )
@@ -368,6 +489,10 @@ EOT
368
489
  The top-level account that is used for all revenue related charges.
369
490
  EOT
370
491
  )
492
+
493
+ pattern([ '_-' ], lambda {
494
+ [ nil, nil ]
495
+ })
371
496
  end
372
497
 
373
498
  def rule_bookingAttributes
@@ -383,7 +508,7 @@ EOT
383
508
  @booking.overtime = @val[1]
384
509
  })
385
510
  doc('overtime.booking', <<'EOT'
386
- This attribute enables bookings during off-hours and vacations. It implicitly
511
+ This attribute enables bookings during off-hours and leaves. It implicitly
387
512
  sets the [[sloppy.booking|sloppy]] attribute accordingly.
388
513
  EOT
389
514
  )
@@ -406,7 +531,7 @@ EOT
406
531
  })
407
532
  doc('sloppy.booking', <<'EOT'
408
533
  Controls how strict TaskJuggler checks booking intervals for conflicts with
409
- working periods and vacations. This attribute only affects the check for
534
+ working periods and leaves. This attribute only affects the check for
410
535
  conflicts. No assignments will be made unless the [[overtime.booking|
411
536
  overtime]] attribute is set accordingly.
412
537
  EOT
@@ -462,20 +587,20 @@ EOT
462
587
  end
463
588
  if masterAccounts.include?(chargeSet.master)
464
589
  error('chargeset_master',
465
- "All charge sets for this task must have different top-level " +
466
- "accounts.", @sourceFileInfo[0], @property)
590
+ "All charge sets for this property must have different " +
591
+ "top-level accounts.", @sourceFileInfo[0], @property)
467
592
  end
468
593
  @property['chargeset', @scenarioIdx] =
469
594
  @property['chargeset', @scenarioIdx] + [ chargeSet ]
470
595
  })
471
596
  doc('chargeset', <<'EOT'
472
- A chargeset defines how the turnover associated with the task will be charged
473
- to one or more accounts. A task may have any number of charge sets, but each
474
- chargeset must deal with a different top-level account. A charge set consists
475
- of one or more accounts. Each account must be a leaf account. The account ID
476
- may be followed by a percentage value that determines the share for this
477
- account. The total percentage of all accounts must be exactly 100%. If some
478
- accounts don't have a percentage specification, the remainder to 100% is
597
+ A chargeset defines how the turnover associated with the property will be
598
+ charged to one or more accounts. A property may have any number of charge sets,
599
+ but each chargeset must deal with a different top-level account. A charge set
600
+ consists of one or more accounts. Each account must be a leaf account. The
601
+ account ID may be followed by a percentage value that determines the share for
602
+ this account. The total percentage of all accounts must be exactly 100%. If
603
+ some accounts don't have a percentage specification, the remainder to 100% is
479
604
  distributed evenly to them.
480
605
  EOT
481
606
  )
@@ -500,6 +625,20 @@ EOT
500
625
 
501
626
  def rule_chargeSetItem
502
627
  pattern(%w( !accountId !optionalPercent ), lambda {
628
+ if @property.is_a?(Task)
629
+ aggregate = :tasks
630
+ elsif @property.is_a?(Resource)
631
+ aggregate = :resources
632
+ else
633
+ raise "Unknown property type #{@property.class}"
634
+ end
635
+
636
+ if @val[0].get('aggregate') != aggregate
637
+ error('account_bad_aggregate',
638
+ "The account #{@val[0].fullId} cannot aggregate amounts " +
639
+ "related to #{aggregate}.")
640
+ end
641
+
503
642
  [ @val[0], @val[1] ]
504
643
  })
505
644
  arg(0, 'account', 'The ID of a previously defined leaf account.')
@@ -883,21 +1022,22 @@ EOT
883
1022
 
884
1023
  def rule_exportHeader
885
1024
  pattern(%w( _export !optionalID $STRING ), lambda {
886
- report = newReport(@val[1], @val[2], :export, @sourceFileInfo[0])
1025
+ newReport(@val[1], @val[2], :export, @sourceFileInfo[0])
1026
+ @property.set('formats', [ :tjp ])
887
1027
 
888
1028
  # By default, we export all scenarios.
889
1029
  scenarios = Array.new(@project.scenarios.items) { |i| i }
890
1030
  scenarios.delete_if { |sc| !@project.scenario(sc).get('active') }
891
- report.set('scenarios', scenarios)
1031
+ @property.set('scenarios', scenarios)
892
1032
  # Show all tasks, sorted by seqno-up.
893
- report.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
894
- report.set('sortTasks', [ [ 'seqno', true, -1 ] ])
1033
+ @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
1034
+ @property.set('sortTasks', [ [ 'seqno', true, -1 ] ])
895
1035
  # Show all resources, sorted by seqno-up.
896
- report.set('hideResource',
897
- LogicalExpression.new(LogicalOperation.new(0)))
898
- report.set('sortResources', [ [ 'seqno', true, -1 ] ])
1036
+ @property.set('hideResource',
1037
+ LogicalExpression.new(LogicalOperation.new(0)))
1038
+ @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
899
1039
  })
900
- arg(1, 'file name', <<'EOT'
1040
+ arg(2, 'file name', <<'EOT'
901
1041
  The name of the report file to generate. It must end with a .tjp or .tji
902
1042
  extension, or use . to use the standard output channel.
903
1043
  EOT
@@ -940,7 +1080,7 @@ EOT
940
1080
  )
941
1081
  allOrNothingListRule('exportableResourceAttributes',
942
1082
  { 'booking' => 'Include bookings',
943
- 'vacation' => 'Include vacations',
1083
+ 'leaves' => 'Include leaves',
944
1084
  'workinghours' => 'Include working hours' })
945
1085
 
946
1086
  pattern(%w( !rollupresource ))
@@ -1418,6 +1558,15 @@ EOT
1418
1558
  pattern(['_isresource', '_(', '_)' ])
1419
1559
  doc('isresource', 'The result is true if the property is a resource.')
1420
1560
 
1561
+ pattern(%w( _isresponsibilityof _( $ID _, $ID _) ))
1562
+ doc('isresponsibilityof', <<'EOT'
1563
+ Will evaluate to true for tasks that have the specified resource
1564
+ assigned as [[responsible]] in the specified scenario.
1565
+ EOT
1566
+ )
1567
+ arg(2, 'Resource ID', 'The ID of a defined resource')
1568
+ arg(4, 'Scenario ID', 'A scenario ID')
1569
+
1421
1570
  pattern(['_istask', '_(', '_)' ])
1422
1571
  doc('istask', 'The result is true if the property is a task.')
1423
1572
 
@@ -1461,6 +1610,19 @@ EOT
1461
1610
  )
1462
1611
  end
1463
1612
 
1613
+ def rule_hideaccount
1614
+ pattern(%w( _hideaccount !logicalExpression ), lambda {
1615
+ @property.set('hideAccount', @val[1])
1616
+ })
1617
+ doc('hideaccount', <<'EOT'
1618
+ Do not include accounts that match the specified logical expression. If the
1619
+ report is sorted in ''''tree'''' mode (default) then enclosing accounts are
1620
+ listed even if the expression matches the account.
1621
+ EOT
1622
+ )
1623
+ also(%w( sortaccounts ))
1624
+ end
1625
+
1464
1626
  def rule_hidejournalentry
1465
1627
  pattern(%w( _hidejournalentry !flagLogicalExpression ), lambda {
1466
1628
  @property.set('hideJournalEntry', @val[1])
@@ -1530,8 +1692,9 @@ EOT
1530
1692
  unless @project.scenario(sc).get('active')
1531
1693
  warning('ical_sc_disabled',
1532
1694
  "Scenario #{sc} has been disabled")
1695
+ else
1696
+ @property.set('scenarios', [ @val[1] ])
1533
1697
  end
1534
- @property.set('scenarios', [ @val[1] ])
1535
1698
  })
1536
1699
  doc('scenario.ical', <<'EOT'
1537
1700
  Id of the scenario that should be included in the report. By default, the
@@ -1543,21 +1706,23 @@ EOT
1543
1706
 
1544
1707
  def rule_iCalReportHeader
1545
1708
  pattern(%w( _icalreport !optionalID $STRING ), lambda {
1546
- report = newReport(@val[1], @val[2], :iCal, @sourceFileInfo[0])
1547
-
1709
+ newReport(@val[1], @val[2], :iCal, @sourceFileInfo[0])
1548
1710
  @property.set('formats', [ :iCal ])
1711
+
1549
1712
  # By default, we export only the first scenario.
1550
- report.set('scenarios', [ 0 ])
1713
+ unless @project.scenario(0).get('active')
1714
+ @property.set('scenarios', [ 0 ])
1715
+ end
1551
1716
  # Show all tasks, sorted by seqno-up.
1552
- report.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
1553
- report.set('sortTasks', [ [ 'seqno', true, -1 ] ])
1717
+ @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
1718
+ @property.set('sortTasks', [ [ 'seqno', true, -1 ] ])
1554
1719
  # Show all resources, sorted by seqno-up.
1555
- report.set('hideResource',
1556
- LogicalExpression.new(LogicalOperation.new(0)))
1557
- report.set('sortResources', [ [ 'seqno', true, -1 ] ])
1720
+ @property.set('hideResource',
1721
+ LogicalExpression.new(LogicalOperation.new(0)))
1722
+ @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
1558
1723
  # Show all journal entries.
1559
- report.set('hideJournalEntry',
1560
- LogicalExpression.new(LogicalOperation.new(0)))
1724
+ @property.set('hideJournalEntry',
1725
+ LogicalExpression.new(LogicalOperation.new(0)))
1561
1726
  })
1562
1727
  arg(1, 'file name', <<'EOT'
1563
1728
  The name of the report file to generate without an extension. Use . to use
@@ -1869,17 +2034,11 @@ EOT
1869
2034
  optional
1870
2035
  repeatable
1871
2036
 
1872
- pattern(%w( _alert $ID ), lambda {
1873
- level = @project.alertLevelIndex(@val[1])
1874
- unless level
1875
- error('bad_alert', "Unknown alert level #{@val[1]}. Must be " +
1876
- 'green, yellow or red', @sourceFileInfo[0])
1877
- end
1878
- @journalEntry.alertLevel = level
2037
+ pattern(%w( _alert !alertLevel ), lambda {
2038
+ @journalEntry.alertLevel = @val[1]
1879
2039
  })
1880
2040
  doc('alert', <<'EOT'
1881
- Specify the alert level for this entry. Supported values are green, yellow and
1882
- red. The default value is green. This attribute is inteded to be used for
2041
+ Specify the alert level for this entry. This attribute is inteded to be used for
1883
2042
  status reporting. When used for a journal entry that is associated with a
1884
2043
  property, the value can be reported in the alert column. When multiple entries
1885
2044
  have been specified for the property, the entry with the date closest to the
@@ -1960,6 +2119,98 @@ EOT
1960
2119
  arg(0, 'resource', 'The ID of a leaf resource')
1961
2120
  end
1962
2121
 
2122
+ def rule_leave
2123
+ pattern(%w( !leaveType !vacationName !intervalOrDate ), lambda {
2124
+ Leave.new(@val[0].intern, @val[2], @val[1])
2125
+ })
2126
+ end
2127
+
2128
+ def rule_leaveList
2129
+ listRule('moreLeaveList', '!leave')
2130
+ end
2131
+
2132
+ def rule_leaveName
2133
+ optional
2134
+ pattern(%w( $STRING ), lambda {
2135
+ @val[0]
2136
+ })
2137
+ arg(0, 'name', 'An optional name or reason for the leave')
2138
+ end
2139
+
2140
+ def rule_leaveAllowance
2141
+ pattern(%w( _annual !valDate !optionalMinus !workingDuration ), lambda {
2142
+ LeaveAllowance.new(:annual, @val[1], (@val[2] ? -1 : 1) * @val[3])
2143
+ })
2144
+ end
2145
+
2146
+ def rule_leaveAllowanceList
2147
+ listRule('moreLeaveAllowanceList', '!leaveAllowance')
2148
+ end
2149
+
2150
+ def rule_leaveAllowances
2151
+ pattern(%w( _leaveallowances !leaveAllowanceList ), lambda {
2152
+ appendScListAttribute('leaveallowances', @val[1])
2153
+ })
2154
+ doc('leaveallowance', <<'EOT'
2155
+ Add or subtract leave allowances. Currently, only allowances for the annual
2156
+ leaves are supported. Allowances can be negative to deal with expired
2157
+ allowances. The ''''leaveallowancebalance'''' report [[columns|column]] can be
2158
+ used to report the current annual leave balance.
2159
+
2160
+ Leaves outside of the project period are silently ignored and will not be
2161
+ considered in the leave balance calculation. Therefor, leave allowances are
2162
+ only allowed within the project period.
2163
+ EOT
2164
+ )
2165
+ level(:beta)
2166
+ example('Leave')
2167
+ end
2168
+
2169
+ def rule_leaves
2170
+ pattern(%w( _leaves !leaveList ), lambda {
2171
+ LeaveList.new(@val[1])
2172
+ })
2173
+ doc('leaves', <<'EOT'
2174
+ Describe a list of leave periods. A leave can be due to a public holiday,
2175
+ personal or sick leave. At global scope, the leaves determine which day is
2176
+ considered a working day. Subsequent resource definitions will inherit the
2177
+ leave list.
2178
+
2179
+ Leaves can be defined at global level, at resource level and at shift level
2180
+ and intervals may overlap. The leave types have different priorities. A higher
2181
+ priority leave type can overwrite a lower priority type. This means that
2182
+ resource level leaves can overwrite global leaves when they have a higher
2183
+ priority. A sub resource can overwrite a leave of a enclosing resource.
2184
+
2185
+ Leave periods outside of the project interval are silently ignored. For leave
2186
+ periods that are partially outside of the project period only the part inside
2187
+ the project period will be considered.
2188
+ EOT
2189
+ )
2190
+ level(:beta)
2191
+ example('Leave')
2192
+ end
2193
+
2194
+ def rule_leaveType
2195
+ singlePattern('_project')
2196
+ descr('Assignment to another project (lowest priority)')
2197
+
2198
+ singlePattern('_annual')
2199
+ descr('Personal leave based on annual allowance')
2200
+
2201
+ singlePattern('_special')
2202
+ descr('Personal leave based on a special occasion')
2203
+
2204
+ singlePattern('_sick')
2205
+ descr('Sick leave')
2206
+
2207
+ singlePattern('_unpaid')
2208
+ descr('Unpaid leave')
2209
+
2210
+ singlePattern('_holiday')
2211
+ descr('Public or bank holiday (highest priority)')
2212
+ end
2213
+
1963
2214
  def rule_limitAttributes
1964
2215
  optionsRule('limitAttributesBody')
1965
2216
  end
@@ -2296,10 +2547,6 @@ EOT
2296
2547
  commaListRule('!journalSortCriterium')
2297
2548
  end
2298
2549
 
2299
- def rule_moreLeafResources
2300
- commaListRule('!resourceLeafList')
2301
- end
2302
-
2303
2550
  def rule_moreListOfDays
2304
2551
  commaListRule('!weekDayInterval')
2305
2552
  end
@@ -2333,6 +2580,7 @@ Defines a navigator object with the specified ID. This object can be used in
2333
2580
  reports to include a navigation bar with references to other reports.
2334
2581
  EOT
2335
2582
  )
2583
+ example('navigator')
2336
2584
  end
2337
2585
 
2338
2586
  def rule_navigatorAttributes
@@ -2512,6 +2760,7 @@ EOT
2512
2760
  error('operand_unkn_scen', "Unknown scenario ID #{scenario}",
2513
2761
  @sourceFileInfo[0])
2514
2762
  end
2763
+ # TODO: Do at least some basic sanity checks of the attribute is valid.
2515
2764
  LogicalAttribute.new(attribute, @project.scenario(scenarioIdx))
2516
2765
  })
2517
2766
  pattern(%w( !date ), lambda {
@@ -2629,6 +2878,13 @@ EOT
2629
2878
  )
2630
2879
  end
2631
2880
 
2881
+ def rule_optionalMinus
2882
+ optional
2883
+ pattern(%w( _- ), lambda {
2884
+ true
2885
+ })
2886
+ end
2887
+
2632
2888
  def rule_optionalPercent
2633
2889
  optional
2634
2890
  pattern(%w( !number _% ), lambda {
@@ -2697,6 +2953,44 @@ EOT
2697
2953
  repeatable
2698
2954
  optional
2699
2955
 
2956
+ pattern(%w( _alertlevels !alertLevelDefinitions ), lambda {
2957
+ if @val[1].length < 2
2958
+ error('too_few_alert_levels',
2959
+ 'You must specify at least 2 different alert levels.',
2960
+ @sourceFileInfo[1])
2961
+ end
2962
+ levels = @project['alertLevels']
2963
+ levels.clear
2964
+ @val[1].each do |level|
2965
+ if levels.indexById(level[0])
2966
+ error('alert_level_redef',
2967
+ "Alert level '#{level[0]}' has been defined multiple times.",
2968
+ @sourceFileInfo[1])
2969
+ end
2970
+
2971
+ if levels.indexByName(level[1])
2972
+ error('alert_name_redef',
2973
+ "Alert level name '#{level[1]}' has been defined multiple " +
2974
+ "times.", @sourceFileInfo[1])
2975
+ end
2976
+
2977
+ @project['alertLevels'].add(AlertLevelDefinition.new(*level))
2978
+ end
2979
+ })
2980
+ level(:beta)
2981
+ doc('alertlevels', <<'EOT'
2982
+ By default TaskJuggler supports the pre-defined alert levels: green, yellow
2983
+ and red. This attribute can be used to replace them with your own set of alert
2984
+ levels. You can define any number of levels, but you need to define at least
2985
+ two and they must be specified in ascending order from the least severity to
2986
+ highest severity. Additionally, you need to provide a 15x15 pixel image file
2987
+ with the name ''''flag-X.png'''' for each level where ''''X'''' matches the ID
2988
+ of the alert level. These files need to be in the ''''icons'''' directory to
2989
+ be found by the browser when showing HTML reports.
2990
+ EOT
2991
+ )
2992
+ example('AlertLevels')
2993
+
2700
2994
  pattern(%w( !currencyFormat ), lambda {
2701
2995
  @project['currencyFormat'] = @val[0]
2702
2996
  })
@@ -2860,7 +3154,7 @@ to the specified workinghours and vacation. It affects the conversion of
2860
3154
  working hours, working days, working weeks, working months and working years
2861
3155
  into each other.
2862
3156
 
2863
- When public holidays and vacations are disregarded, this value should be equal
3157
+ When public holidays and leaves are disregarded, this value should be equal
2864
3158
  to the number of working days per week times 52.1428 (the average number of
2865
3159
  weeks per year). E. g. for a culture with 5 working days it is 260.714 (the
2866
3160
  default), for 6 working days it is 312.8568 and for 7 working days it is
@@ -2919,26 +3213,18 @@ EOT
2919
3213
  def rule_projectionAttributes
2920
3214
  optional
2921
3215
  repeatable
2922
- pattern(%w( _sloppy ), lambda {
2923
- warning('projection_sloppy',
2924
- 'The sloppy projection mode has been deprecated. The ' +
2925
- 'functionality is no longer supported.')
2926
- })
2927
- doc('sloppy.projection', <<'EOT'
2928
- The sloppy projection mode has been deprecated. Please use
2929
- [[trackingscenario]] feature instead.
2930
- EOT
2931
- )
3216
+ pattern(%w( _sloppy ))
3217
+ level(:deprecated)
3218
+ also('trackingscenario')
3219
+ doc('sloppy.projection', '')
2932
3220
 
2933
3221
  pattern(%w( _strict ), lambda {
2934
3222
  warning('projection_strict',
2935
3223
  'The strict mode is now always used.')
2936
3224
  })
2937
- doc('strict.projection', <<'EOT'
2938
- The strict projection mode has been deprecated. Please use
2939
- [[trackingscenario]] feature instead.
2940
- EOT
2941
- )
3225
+ level(:deprecated)
3226
+ also('trackingscenario')
3227
+ doc('strict.projection', '')
2942
3228
  end
2943
3229
 
2944
3230
  def rule_projectProlog
@@ -2969,15 +3255,13 @@ EOT
2969
3255
  lastSyntaxToken(1)
2970
3256
  doc('include.project', <<'EOT'
2971
3257
  Includes the specified file name as if its contents would be written
2972
- instead of the include property. The only exception is the include
2973
- statement itself. When the included files contains other include
2974
- statements or report definitions, the filenames are relative to file
3258
+ instead of the include property. When the included files contains other
3259
+ include statements or report definitions, the filenames are relative to file
2975
3260
  where they are defined in.
2976
3261
 
2977
- The included files may only contain content that may be present in a project
2978
- header section.
2979
-
2980
- If the include statement is the last statement in the file it must have the option block. The option block can be empty, but the curly braces must be present.
3262
+ This version of the include directive may only be used inside the [[project]]
3263
+ header section. The included files must only contain content that may be
3264
+ present in a project header section.
2981
3265
  EOT
2982
3266
  )
2983
3267
  end
@@ -2992,7 +3276,8 @@ statement itself. When the included files contains other include
2992
3276
  statements or report definitions, the filenames are relative to file
2993
3277
  where they are defined in.
2994
3278
 
2995
- The included file may only contain macro definitions.
3279
+ The included file may only contain macro definitions. This version of the
3280
+ include directive can only be used before the [[project]] header.
2996
3281
  EOT
2997
3282
  )
2998
3283
  end
@@ -3021,8 +3306,6 @@ EOT
3021
3306
  @project['revenueAccount'] = @val[0][1]
3022
3307
  })
3023
3308
 
3024
- pattern(%w( !export ))
3025
-
3026
3309
  pattern(%w( _flags !declareFlagList ), lambda {
3027
3310
  unless @project['flags'].include?(@val[1])
3028
3311
  @project['flags'] += @val[1]
@@ -3033,9 +3316,14 @@ Declare one or more flag for later use. Flags can be used to mark tasks, resourc
3033
3316
  EOT
3034
3317
  )
3035
3318
 
3036
- pattern(%w( !iCalReport ))
3037
3319
  pattern(%w( !propertiesInclude ))
3038
3320
 
3321
+ pattern(%w( !leaves ), lambda {
3322
+ @val[0].each do |v|
3323
+ @project['leaves'] << v
3324
+ end
3325
+ })
3326
+
3039
3327
  pattern(%w( !limits ), lambda {
3040
3328
  @project['limits'] = @val[0]
3041
3329
  })
@@ -3048,8 +3336,6 @@ EOT
3048
3336
 
3049
3337
  pattern(%w( !macro ))
3050
3338
 
3051
- pattern(%w( !nikuReport ))
3052
-
3053
3339
  pattern(%w( !navigator ))
3054
3340
 
3055
3341
  pattern(%w( _projectid $ID ), lambda {
@@ -3082,12 +3368,10 @@ Set the default rate for all subsequently defined resources. The rate describes
3082
3368
  EOT
3083
3369
  )
3084
3370
 
3085
- pattern(%w( !report ))
3371
+ pattern(%w( !reportProperties ))
3086
3372
  pattern(%w( !resource ))
3087
- pattern(%w( !tagfile ))
3088
3373
  pattern(%w( !shift ))
3089
3374
  pattern(%w( !statusSheet ))
3090
- pattern(%w( !statusSheetReport ))
3091
3375
 
3092
3376
  pattern(%w( _supplement !supplement ))
3093
3377
  doc('supplement', <<'EOT'
@@ -3105,10 +3389,11 @@ EOT
3105
3389
 
3106
3390
  pattern(%w( !task ))
3107
3391
  pattern(%w( !timeSheet ))
3108
- pattern(%w( !timeSheetReport ))
3109
3392
  pattern(%w( _vacation !vacationName !intervals ), lambda {
3110
3393
  begin
3111
- @project['vacations'] = @project['vacations'] + @val[2]
3394
+ @val[2].each do |interval|
3395
+ @project['leaves'] << Leave.new(:holiday, interval)
3396
+ end
3112
3397
  rescue AttributeOverwrite
3113
3398
  end
3114
3399
  })
@@ -3129,6 +3414,7 @@ EOT
3129
3414
  def rule_propertiesInclude
3130
3415
  pattern(%w( _include !includeProperties !properties . ), lambda {
3131
3416
  })
3417
+ lastSyntaxToken(1)
3132
3418
  doc('include.properties', <<'EOT'
3133
3419
  Includes the specified file name as if its contents would be written
3134
3420
  instead of the include property. The only exception is the include
@@ -3157,11 +3443,6 @@ EOT
3157
3443
  else
3158
3444
  attr = @property.get(@val[1])
3159
3445
  end
3160
- unless attr.is_a?(Array)
3161
- error('purge_no_list',
3162
- "#{@val[1]} is not a list attribute. Only those can be purged.",
3163
- @sourceFileInfo[1])
3164
- end
3165
3446
  if @property.attributeDefinition(@val[1]).scenarioSpecific
3166
3447
  @property.getAttribute(@val[1], @scenarioIdx).reset
3167
3448
  else
@@ -3169,11 +3450,16 @@ EOT
3169
3450
  end
3170
3451
  })
3171
3452
  doc('purge', <<'EOT'
3172
- List attributes, like regular attributes, can inherit their values from the
3173
- enclosing property. By defining more values for such a list attribute, the new
3174
- values will be appended to the existing ones. The purge statement clears such
3175
- a list atribute. A subsequent definition for the attribute within the property
3176
- will then add their values to an empty list.
3453
+ Many attributes inherit their values from the enclosing property or the global
3454
+ scope. In certain circumstances, this is not desirable, e. g. for list
3455
+ attributes. A list attribute is any attribute that takes a comma separated
3456
+ list of values as argument. [[allocate]] and [[flags.task]] are
3457
+ good examples of commonly used list attributes. By defining values for
3458
+ such a list attribute in a nested property, the new values will be appended to
3459
+ the list that was inherited from the enclosing property. The purge
3460
+ attribute resets any attribute to its default value. A subsequent definition
3461
+ for the attribute within the property will then add their values to an empty
3462
+ list. The value of the enclosing property is not affected by purge.
3177
3463
  EOT
3178
3464
  )
3179
3465
  arg(1, 'attribute', 'Any name of a list attribute')
@@ -3202,35 +3488,29 @@ EOT
3202
3488
  })
3203
3489
  end
3204
3490
 
3205
- def rule_report
3206
- pattern(%w( !reportHeader !reportBody ), lambda {
3207
- @property = @property.parent
3208
- })
3209
- doc('report', <<'EOT'
3210
- Reports are used to store and vizualize the results of a scheduled project.
3211
- The content, the output format and the appearance of a report can be adjusted
3212
- with report attributes. Reports can be nested to create structured document
3213
- trees. As with other properties, the resource attributes can be inherited from
3214
- the enclosing report or the project.
3215
3491
 
3216
- By default, report definitions do not generate any files. With more complex
3217
- projects, most report definitions will be used to describe elements of
3218
- composed reports. If you want to generate a file from this report, you must
3219
- specify the list of [[formats]] that you want to generate. The report name
3220
- will then be used as a base name to create the file. The suffix will be
3221
- appended based on the generated format.
3492
+ def rule_reports
3493
+ pattern(%w( !accountReport ))
3494
+ pattern(%w( !resourceReport ))
3495
+ pattern(%w( !taskReport ))
3496
+ pattern(%w( !textReport ))
3497
+ end
3222
3498
 
3223
- Reports have a local name space. All IDs must be unique within the reports
3224
- that belong to the same enclosing report. To reference a report for inclusion
3225
- into another report, you need to specify the full report ID. This is composed
3226
- of the report ID, prefixed by a dot-separated list of all parent report IDs.
3499
+ def rule_reportableAttributes
3500
+ singlePattern('_annualleave')
3501
+ descr(<<'EOT'
3502
+ The number of annual leave units within the reported time period. The unit
3503
+ can be adjusted with [[loadunit]].
3227
3504
  EOT
3228
- )
3229
- also(%w( resourcereport taskreport textreport ))
3230
- end
3505
+ )
3231
3506
 
3507
+ singlePattern('_annualleavebalance')
3508
+ descr(<<'EOT'
3509
+ The balance of the annual leave at the end of the reporting interval. The unit
3510
+ can be adjusted with [[loadunit]].
3511
+ EOT
3512
+ )
3232
3513
 
3233
- def rule_reportableAttributes
3234
3514
  singlePattern('_alert')
3235
3515
  descr(<<'EOT'
3236
3516
  The alert level of the property that was reported with the date closest to the
@@ -3242,9 +3522,13 @@ EOT
3242
3522
  )
3243
3523
 
3244
3524
  singlePattern('_alertmessages')
3525
+ level(:deprecated)
3526
+ also('journal')
3245
3527
  descr('Deprecated. Please use ''''journal'''' instead')
3246
3528
 
3247
3529
  singlePattern('_alertsummaries')
3530
+ level(:deprecated)
3531
+ also('journal')
3248
3532
  descr('Deprecated. Please use ''''journal'''' instead')
3249
3533
 
3250
3534
  singlePattern('_alerttrend')
@@ -3255,6 +3539,12 @@ or flat.
3255
3539
  EOT
3256
3540
  )
3257
3541
 
3542
+ singlePattern('_balance')
3543
+ descr('The account balance at the beginning of the reported period.')
3544
+
3545
+ singlePattern('_bsi')
3546
+ descr('The hierarchical or work breakdown structure index (i. e. 1.2.3)')
3547
+
3258
3548
  singlePattern('_chart')
3259
3549
  descr(<<'EOT'
3260
3550
  A Gantt chart. This column type requires all lines to have the same fixed
@@ -3282,6 +3572,8 @@ EOT
3282
3572
  pattern([ '_completed' ], lambda {
3283
3573
  'complete'
3284
3574
  })
3575
+ level(:deprecated)
3576
+ also('complete')
3285
3577
  descr('Deprecated alias for complete')
3286
3578
 
3287
3579
  singlePattern('_criticalness')
@@ -3368,17 +3660,35 @@ EOT
3368
3660
  descr(<<'EOT'
3369
3661
  The Full-Time-Equivalent of a resource or group. This is the ratio of the
3370
3662
  resource working time and the global working time. Working time is defined by
3371
- working hours and vacations. The FTE value can vary over time and is
3663
+ working hours and leaves. The FTE value can vary over time and is
3372
3664
  calculated for the report interval or the user specified interval.
3665
+ EOT
3666
+ )
3667
+
3668
+ singlePattern('_gauge')
3669
+ descr(<<'EOT'
3670
+ When [[complete]] values have been provided to capture the actual progress on
3671
+ tasks, the gauge column will list whether the task is ahead of, behind or on
3672
+ schedule.
3373
3673
  EOT
3374
3674
  )
3375
3675
 
3376
3676
  singlePattern('_headcount')
3377
- descr('The headcount number of the resource or group')
3677
+ descr(<<'EOT'
3678
+ For resources this is the headcount number of the resource or resource group.
3679
+ For a single resource this is the [[efficiency]] rounded to the next integer.
3680
+ For a group it is the sum of the sub resources headcount.
3681
+
3682
+ For tasks it's the number of different resources allocated to the task during
3683
+ the report interval. Resources are weighted with their rounded efficiencies.
3684
+ EOT
3685
+ )
3378
3686
 
3379
3687
  pattern([ '_hierarchindex' ], lambda {
3380
3688
  'bsi'
3381
3689
  })
3690
+ level(:deprecated)
3691
+ also('bsi')
3382
3692
  descr('Deprecated alias for bsi')
3383
3693
 
3384
3694
  singlePattern('_hourly')
@@ -3411,12 +3721,18 @@ EOT
3411
3721
  )
3412
3722
 
3413
3723
  singlePattern('_journal_sub')
3724
+ level(:deprecated)
3725
+ also('journal')
3414
3726
  descr('Deprecated. Please use ''''journal'''' instead')
3415
3727
 
3416
3728
  singlePattern('_journalmessages')
3729
+ level(:deprecated)
3730
+ also('journal')
3417
3731
  descr('Deprecated. Please use ''''journal'''' instead')
3418
3732
 
3419
3733
  singlePattern('_journalsummaries')
3734
+ level(:deprecated)
3735
+ also('journal')
3420
3736
  descr('Deprecated. Please use ''''journal'''' instead')
3421
3737
 
3422
3738
  singlePattern('_line')
@@ -3521,6 +3837,20 @@ EOT
3521
3837
  singlePattern('_seqno')
3522
3838
  descr('The index of the item based on the declaration order')
3523
3839
 
3840
+ singlePattern('_sickleave')
3841
+ descr(<<'EOT'
3842
+ The number of sick leave units within the reported time period. The unit can
3843
+ be adjusted with [[loadunit]].
3844
+ EOT
3845
+ )
3846
+
3847
+ singlePattern('_specialleave')
3848
+ descr(<<'EOT'
3849
+ The number of special leave units within the reported time period. The unit
3850
+ can be adjusted with [[loadunit]].
3851
+ EOT
3852
+ )
3853
+
3524
3854
  singlePattern('_start')
3525
3855
  descr('The start date of the task')
3526
3856
 
@@ -3544,10 +3874,16 @@ EOT
3544
3874
  pattern([ '_wbs' ], lambda {
3545
3875
  'bsi'
3546
3876
  })
3877
+ level(:deprecated)
3878
+ also('bsi')
3547
3879
  descr('Deprecated alias for bsi.')
3548
3880
 
3549
- singlePattern('_bsi')
3550
- descr('The hierarchical or work breakdown structure index')
3881
+ singlePattern('_unpaidleave')
3882
+ descr(<<'EOT'
3883
+ The number of unpaid leave units within the reported time period. The unit
3884
+ can be adjusted with [[loadunit]].
3885
+ EOT
3886
+ )
3551
3887
 
3552
3888
  singlePattern('_weekly')
3553
3889
  descr('A group of columns with one column for each week')
@@ -3561,6 +3897,23 @@ EOT
3561
3897
  optional
3562
3898
  repeatable
3563
3899
 
3900
+ pattern(%w( _accountroot !accountId), lambda {
3901
+ if @val[1].leaf?
3902
+ error('accountroot_leaf',
3903
+ "#{@val[1].fullId} is not a container account",
3904
+ @sourceFileInfo[1])
3905
+ end
3906
+ @property.set('accountRoot', @val[1])
3907
+ })
3908
+ doc('accountroot', <<'EOT'
3909
+ Only accounts below the specified root-level accounts are exported. The exported
3910
+ accounts will have the ID of the root-level account stripped from their ID, so that
3911
+ the sub-accounts of the root-level account become top-level accounts in the report
3912
+ file.
3913
+ EOT
3914
+ )
3915
+ example('AccountReport')
3916
+
3564
3917
  pattern(%w( !balance ), lambda {
3565
3918
  @property.set('costAccount', @val[0][0])
3566
3919
  @property.set('revenueAccount', @val[0][1])
@@ -3586,6 +3939,7 @@ be interpreted as [[Rich_Text_Attributes|Rich Text]].
3586
3939
  EOT
3587
3940
  )
3588
3941
  arg(1, 'text', 'The text')
3942
+ example('textreport')
3589
3943
 
3590
3944
  pattern(%w( _columns !columnDef !moreColumnDef ), lambda {
3591
3945
  columns = [ @val[1] ]
@@ -3631,6 +3985,7 @@ Define a text section that is put at the bottom of the report. The
3631
3985
  text will be interpreted as [[Rich_Text_Attributes|Rich Text]].
3632
3986
  EOT
3633
3987
  )
3988
+ example('textreport')
3634
3989
  also(%w( epilog header prolog ))
3635
3990
 
3636
3991
  pattern(%w( !formats ))
@@ -3643,10 +3998,12 @@ Define a text section that is put at the top of the report. The
3643
3998
  text will be interpreted as [[Rich_Text_Attributes|Rich Text]].
3644
3999
  EOT
3645
4000
  )
4001
+ example('textreport')
3646
4002
  also(%w( epilog footer prolog ))
3647
4003
 
3648
4004
  pattern(%w( !headline ))
3649
4005
  pattern(%w( !hidejournalentry ))
4006
+ pattern(%w( !hideaccount ))
3650
4007
  pattern(%w( !hideresource ))
3651
4008
  pattern(%w( !hidetask ))
3652
4009
  pattern(%w( !journalReportAttributes ))
@@ -3667,6 +4024,7 @@ will be interpreted as [[Rich_Text_Attributes|Rich Text]]. The margin will not
3667
4024
  span the [[header]] or [[footer]] sections.
3668
4025
  EOT
3669
4026
  )
4027
+ example('textreport')
3670
4028
 
3671
4029
  pattern(%w( _loadunit !loadunit ), lambda {
3672
4030
  @property.set('loadUnit', @val[1])
@@ -3698,7 +4056,7 @@ EOT
3698
4056
  also(%w( epilog footer header ))
3699
4057
 
3700
4058
  pattern(%w( !purge ))
3701
- pattern(%w( !report ))
4059
+ pattern(%w( !reports ))
3702
4060
 
3703
4061
  pattern(%w( _right $STRING ), lambda {
3704
4062
  @property.set('right', newRichText(@val[1], @sourceFileInfo[1]))
@@ -3709,7 +4067,9 @@ will be interpreted as [[Rich_Text_Attributes|Rich Text]]. The margin will not
3709
4067
  span the [[header]] or [[footer]] sections.
3710
4068
  EOT
3711
4069
  )
4070
+ example('textreport')
3712
4071
 
4072
+ pattern(%w( !rollupaccount ))
3713
4073
  pattern(%w( !rollupresource ))
3714
4074
  pattern(%w( !rolluptask ))
3715
4075
 
@@ -3737,6 +4097,7 @@ used.
3737
4097
  EOT
3738
4098
  )
3739
4099
 
4100
+ pattern(%w( !sortAccounts ))
3740
4101
  pattern(%w( !sortJournalEntries ))
3741
4102
  pattern(%w( !sortResources ))
3742
4103
  pattern(%w( !sortTasks ))
@@ -3834,6 +4195,31 @@ EOT
3834
4195
  singlePattern('$ID')
3835
4196
  end
3836
4197
 
4198
+ def rule_reportName
4199
+ pattern(%w( $STRING ), lambda {
4200
+ @val[0]
4201
+ })
4202
+ arg(0, 'name', <<'EOT'
4203
+ The name of the report. This will be the base name for generated output files.
4204
+ The suffix will depend on the specified [[formats]]. It will also be used in
4205
+ navigation bars.
4206
+
4207
+ By default, report definitions do not generate any files. With more complex
4208
+ projects, most report definitions will be used to describe elements of
4209
+ composed reports. If you want to generate a file from this report, you must
4210
+ specify the list of [[formats]] that you want to generate. The report name
4211
+ will then be used as a base name to create the file. The suffix will be
4212
+ appended based on the generated format.
4213
+
4214
+ Reports have a local name space. All IDs and file names must be unique within
4215
+ the reports that belong to the same enclosing report. To reference a report
4216
+ for inclusion into another report, you need to specify the full report ID.
4217
+ This is composed of the report ID, prefixed by a dot-separated list of all
4218
+ parent report IDs.
4219
+ EOT
4220
+ )
4221
+ end
4222
+
3837
4223
  def rule_reportPeriod
3838
4224
  pattern(%w( _period !interval ), lambda {
3839
4225
  @property.set('start', @val[1].start)
@@ -3846,6 +4232,28 @@ EOT
3846
4232
  )
3847
4233
  end
3848
4234
 
4235
+ def rule_reportProperties
4236
+ pattern(%w( !export ))
4237
+ pattern(%w( !iCalReport ))
4238
+ pattern(%w( !nikuReport ))
4239
+ pattern(%w( !reports ))
4240
+ pattern(%w( !tagfile ))
4241
+ pattern(%w( !statusSheetReport ))
4242
+ pattern(%w( !timeSheetReport ))
4243
+ end
4244
+
4245
+ def rule_reportPropertiesBody
4246
+ optional
4247
+ repeatable
4248
+
4249
+ pattern(%w( !macro ))
4250
+ pattern(%w( !reportProperties ))
4251
+ end
4252
+
4253
+ def rule_reportPropertiesFile
4254
+ pattern(%w( !reportPropertiesBody . ))
4255
+ end
4256
+
3849
4257
  def rule_reportStart
3850
4258
  pattern(%w( _start !date ), lambda {
3851
4259
  if @val[1] > @property.get('end')
@@ -3866,93 +4274,6 @@ EOT
3866
4274
  optionsRule('reportAttributes')
3867
4275
  end
3868
4276
 
3869
- def rule_reportHeader
3870
- pattern(%w( !reportType !optionalID $STRING ), lambda {
3871
- if @property.nil? && !@reportprefix.empty?
3872
- @property = @project.report(@reportprefix)
3873
- end
3874
- if @val[1]
3875
- id = (@property ? @property.fullId + '.' : '') + @val[1]
3876
- if @project.report(id)
3877
- error('report_exists', "report #{id} has already been defined.",
3878
- @sourceFileInfo[1], @property)
3879
- end
3880
- end
3881
- @property = Report.new(@project, @val[1], @val[2], @property)
3882
- @property.sourceFileInfo = @sourceFileInfo[0]
3883
- @property.inheritAttributes
3884
- case @val[0]
3885
- when 'taskreport'
3886
- @property.typeSpec = :taskreport
3887
- unless @property.modified?('columns')
3888
- # Set the default columns for this report.
3889
- %w( bsi name start end effort chart ).each do |col|
3890
- @property.get('columns') <<
3891
- TableColumnDefinition.new(col, columnTitle(col))
3892
- end
3893
- end
3894
- # Show all tasks, sorted by tree, start-up, seqno-up.
3895
- unless @property.modified?('hideTask')
3896
- @property.set('hideTask',
3897
- LogicalExpression.new(LogicalOperation.new(0)))
3898
- end
3899
- unless @property.modified?('softTask')
3900
- @property.set('sortTasks',
3901
- [ [ 'tree', true, -1 ],
3902
- [ 'start', true, 0 ],
3903
- [ 'seqno', true, -1 ] ])
3904
- end
3905
- # Show no resources, but set sorting to id-up.
3906
- unless @property.modified?('hideResource')
3907
- @property.set('hideResource',
3908
- LogicalExpression.new(LogicalOperation.new(1)))
3909
- end
3910
- unless @property.modified?('sortResources')
3911
- @property.set('sortResources', [ [ 'id', true, -1 ] ])
3912
- end
3913
- when 'resourcereport'
3914
- @property.typeSpec = :resourcereport
3915
- if @property.modified?('columns')
3916
- # Set the default columns for this report.
3917
- %w( no name ).each do |col|
3918
- @property.get('columns') <<
3919
- TableColumnDefinition.new(col, columnTitle(col))
3920
- end
3921
- end
3922
- # Show all resources, sorted by tree and id-up.
3923
- unless @property.modified?('hideResource')
3924
- @property.set('hideResource',
3925
- LogicalExpression.new(LogicalOperation.new(0)))
3926
- end
3927
- unless @property.modified?('sortResources')
3928
- @property.set('sortResources', [ [ 'tree', true, -1 ],
3929
- [ 'id', true, -1 ] ])
3930
- end
3931
- # Hide all resources, but set sorting to tree, start-up, seqno-up.
3932
- unless @property.modified?('hideTask')
3933
- @property.set('hideTask',
3934
- LogicalExpression.new(LogicalOperation.new(1)))
3935
- end
3936
- unless @property.modified?('sortTasks')
3937
- @property.set('sortTasks',
3938
- [ [ 'tree', true, -1 ],
3939
- [ 'start', true, 0 ],
3940
- [ 'seqno', true, -1 ] ])
3941
- end
3942
- when 'textreport'
3943
- @property.typeSpec = :textreport
3944
- else
3945
- raise "Unsupported report type #{@val[0]}"
3946
- end
3947
- })
3948
- arg(2, 'name', <<'EOT'
3949
- The name of the report. This will be the base name for generated output files.
3950
- The suffix will depend on the specified [[formats]].It will also be used in
3951
- navigation bars.
3952
- EOT
3953
- )
3954
- end
3955
-
3956
4277
  def rule_reportTitle
3957
4278
  pattern(%w( _title $STRING ), lambda {
3958
4279
  @property.set('title', @val[1])
@@ -3964,47 +4285,6 @@ EOT
3964
4285
  )
3965
4286
  end
3966
4287
 
3967
- def rule_reportType
3968
- singlePattern('_resourcereport')
3969
- doc('resourcereport', <<'EOT'
3970
- The report lists resources and their respective values in a table. The task
3971
- that are the resources are allocated to can be listed as well. To reduce the
3972
- list of included resources, you can use the [[hideresource]],
3973
- [[rollupresource]] or [[resourceroot]] attributes. The order of the task can
3974
- be controlled with [[sortresources]]. If the first sorting criteria is tree
3975
- sorting, the parent resources will always be included to form the tree.
3976
- Tree sorting is the default. You need to change it if you do not want certain
3977
- parent resources to be included in the report.
3978
-
3979
- The tasks that the resources are allocated to can be included as well. Use the
3980
- [[hidetask]] attribute for this. See [[report]] for a complete list of
3981
- attributes and the full syntax for this keyword.
3982
- EOT
3983
- )
3984
- singlePattern('_taskreport')
3985
- doc('taskreport', <<'EOT'
3986
- The report lists tasks and their respective values in a table. To reduce the
3987
- list of included tasks, you can use the [[hidetask]], [[rolluptask]] or
3988
- [[taskroot]] attributes. The order of the task can be controlled with
3989
- [[sorttasks]]. If the first sorting criteria is tree sorting, the parent tasks
3990
- will always be included to form the tree. Tree sorting is the default. You
3991
- need to change it if you do not want certain parent tasks to be included in
3992
- the report.
3993
-
3994
- The resources that are allocated to each task can be listed as well. Use the
3995
- [[hideresource]] attribute for this. See [[report]] for a complete list of
3996
- attributes and the full syntax for this keyword.
3997
- EOT
3998
- )
3999
- singlePattern('_textreport')
4000
- doc('textreport', <<'EOT'
4001
- This report consists of 5 RichText sections, a header, a center section with a
4002
- left and right margin and a footer. The sections may contain the output of
4003
- other defined reports. See [[report]] for further details.
4004
- EOT
4005
- )
4006
- end
4007
-
4008
4288
  def rule_resource
4009
4289
  pattern(%w( !resourceHeader !resourceBody ), lambda {
4010
4290
  @property = @property.parent
@@ -4117,16 +4397,70 @@ EOT
4117
4397
  end
4118
4398
 
4119
4399
  def rule_resourceLeafList
4120
- pattern(%w( !leafResourceId !moreLeafResources ), lambda {
4121
- [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
4122
- })
4400
+ listRule('moreResourceLeafList', '!leafResourceId')
4123
4401
  end
4124
4402
 
4125
4403
  def rule_resourceList
4126
4404
  listRule('moreResources', '!resourceId')
4127
4405
  end
4128
4406
 
4407
+ def rule_resourceReport
4408
+ pattern(%w( !resourceReportHeader !reportBody ), lambda {
4409
+ @property = @property.parent
4410
+ })
4411
+ doc('resourcereport', <<'EOT'
4412
+ The report lists resources and their respective values in a table. The task
4413
+ that are the resources are allocated to can be listed as well. To reduce the
4414
+ list of included resources, you can use the [[hideresource]],
4415
+ [[rollupresource]] or [[resourceroot]] attributes. The order of the task can
4416
+ be controlled with [[sortresources]]. If the first sorting criteria is tree
4417
+ sorting, the parent resources will always be included to form the tree.
4418
+ Tree sorting is the default. You need to change it if you do not want certain
4419
+ parent resources to be included in the report.
4420
+
4421
+ The tasks that the resources are allocated to can be included as well. Use the
4422
+ [[hidetask]] attribute for this.
4423
+ EOT
4424
+ )
4425
+ end
4426
+
4427
+ def rule_resourceReportHeader
4428
+ pattern(%w( _resourcereport !optionalID !reportName ), lambda {
4429
+ newReport(@val[1], @val[2], :resourcereport, @sourceFileInfo[0])
4430
+
4431
+ if @property.modified?('columns')
4432
+ # Set the default columns for this report.
4433
+ %w( no name ).each do |col|
4434
+ @property.get('columns') <<
4435
+ TableColumnDefinition.new(col, columnTitle(col))
4436
+ end
4437
+ end
4438
+ # Show all resources, sorted by tree and id-up.
4439
+ unless @property.modified?('hideResource')
4440
+ @property.set('hideResource',
4441
+ LogicalExpression.new(LogicalOperation.new(0)))
4442
+ end
4443
+ unless @property.modified?('sortResources')
4444
+ @property.set('sortResources', [ [ 'tree', true, -1 ],
4445
+ [ 'id', true, -1 ] ])
4446
+ end
4447
+ # Hide all resources, but set sorting to tree, start-up, seqno-up.
4448
+ unless @property.modified?('hideTask')
4449
+ @property.set('hideTask',
4450
+ LogicalExpression.new(LogicalOperation.new(1)))
4451
+ end
4452
+ unless @property.modified?('sortTasks')
4453
+ @property.set('sortTasks',
4454
+ [ [ 'tree', true, -1 ],
4455
+ [ 'start', true, 0 ],
4456
+ [ 'seqno', true, -1 ] ])
4457
+ end
4458
+ })
4459
+ end
4460
+
4129
4461
  def rule_resourceScenarioAttributes
4462
+ pattern(%w( !chargeset ))
4463
+
4130
4464
  pattern(%w( _efficiency !number ), lambda {
4131
4465
  @property['efficiency', @scenarioIdx] = @val[1]
4132
4466
  })
@@ -4184,6 +4518,15 @@ EOT
4184
4518
 
4185
4519
  pattern(%w( !fail ))
4186
4520
 
4521
+ pattern(%w( !leaveAllowances ))
4522
+
4523
+ pattern(%w( !leaves ), lambda {
4524
+ begin
4525
+ @property['leaves', @scenarioIdx] += @val[0]
4526
+ rescue AttributeOverwrite
4527
+ end
4528
+ })
4529
+
4187
4530
  pattern(%w( !limits ), lambda {
4188
4531
  @property['limits', @scenarioIdx] = @val[0]
4189
4532
  })
@@ -4221,14 +4564,36 @@ The rate specifies the daily cost of the resource.
4221
4564
  EOT
4222
4565
  )
4223
4566
 
4224
- pattern(%w( _shift !shiftAssignments ))
4567
+ pattern(%w( !resourceShiftAssignments !shiftAssignments ), lambda {
4568
+ checkContainer('shifts')
4569
+ # Set same value again to set the 'provided' state for the attribute.
4570
+ begin
4571
+ @property['shifts', @scenarioIdx] = @shiftAssignments
4572
+ rescue AttributeOverwrite
4573
+ # Multiple shift assignments are a common idiom, so don't warn about
4574
+ # them.
4575
+ end
4576
+ @shiftAssignments = nil
4577
+ })
4578
+ level(:deprecated)
4579
+ also('shift.resource')
4225
4580
  doc('shift.resource', <<'EOT'
4226
4581
  This keyword has been deprecated. Please use [[shifts.resource|shifts
4227
4582
  (resource)]] instead.
4228
4583
  EOT
4229
4584
  )
4230
4585
 
4231
- pattern(%w( _shifts !shiftAssignments ))
4586
+ pattern(%w( !resourceShiftsAssignments !shiftAssignments ), lambda {
4587
+ checkContainer('shifts')
4588
+ # Set same value again to set the 'provided' state for the attribute.
4589
+ begin
4590
+ @property['shifts', @scenarioIdx] = @shiftAssignments
4591
+ rescue AttributeOverwrite
4592
+ # Multiple shift assignments are a common idiom, so don't warn about
4593
+ # them.
4594
+ end
4595
+ @shiftAssignments = nil
4596
+ })
4232
4597
  doc('shifts.resource', <<'EOT'
4233
4598
  Limits the working time of a resource to a defined shift during the specified
4234
4599
  interval. Multiple shifts can be defined, but shift intervals may not overlap.
@@ -4239,8 +4604,10 @@ EOT
4239
4604
 
4240
4605
  pattern(%w( _vacation !vacationName !intervals ), lambda {
4241
4606
  begin
4242
- @property['vacations', @scenarioIdx] =
4243
- @property['vacations', @scenarioIdx ] + @val[2]
4607
+ @val[2].each do |interval|
4608
+ # We map the old 'vacation' attribute to public holidays.
4609
+ @property['leaves', @scenarioIdx] << Leave.new(:holiday, interval)
4610
+ end
4244
4611
  rescue AttributeOverwrite
4245
4612
  end
4246
4613
  })
@@ -4258,6 +4625,29 @@ EOT
4258
4625
  # Other attributes will be added automatically.
4259
4626
  end
4260
4627
 
4628
+ def rule_resourceShiftAssignments
4629
+ pattern(%w( _shift ), lambda {
4630
+ @shiftAssignments = @property['shifts', @scenarioIdx]
4631
+ })
4632
+ end
4633
+
4634
+ def rule_resourceShiftsAssignments
4635
+ pattern(%w( _shifts ), lambda {
4636
+ @shiftAssignments = @property['shifts', @scenarioIdx]
4637
+ })
4638
+ end
4639
+
4640
+ def rule_rollupaccount
4641
+ pattern(%w( _rollupaccount !logicalExpression ), lambda {
4642
+ @property.set('rollupAccount', @val[1])
4643
+ })
4644
+ doc('rollupaccount', <<'EOT'
4645
+ Do not show sub-accounts of accounts that match the specified logical
4646
+ expression.
4647
+ EOT
4648
+ )
4649
+ end
4650
+
4261
4651
  def rule_rollupresource
4262
4652
  pattern(%w( _rollupresource !logicalExpression ), lambda {
4263
4653
  @property.set('rollupResource', @val[1])
@@ -4323,6 +4713,8 @@ EOT
4323
4713
  pattern(%w( _disabled ), lambda {
4324
4714
  @property.set('active', false)
4325
4715
  })
4716
+ level(:deprecated)
4717
+ also('active')
4326
4718
  doc('disabled', <<'EOT'
4327
4719
  This attribute is deprecated. Please use [active] instead.
4328
4720
 
@@ -4334,6 +4726,8 @@ EOT
4334
4726
  pattern(%w( _enabled ), lambda {
4335
4727
  @property.set('active', true)
4336
4728
  })
4729
+ level(:deprecated)
4730
+ also('active')
4337
4731
  doc('enabled', <<'EOT'
4338
4732
  This attribute is deprecated. Please use [active] instead.
4339
4733
 
@@ -4342,11 +4736,9 @@ scenario.
4342
4736
  EOT
4343
4737
  )
4344
4738
 
4345
- pattern(%w( _projection !projection ), lambda {
4346
- warning('projection',
4347
- 'The \'projection\' keyword has been deprecated. Please use ' +
4348
- '[[trackingscenario]] feature instead.')
4349
- })
4739
+ pattern(%w( _projection !projection ))
4740
+ level(:deprecated)
4741
+ also('booking.task')
4350
4742
  doc('projection', <<'EOT'
4351
4743
  This keyword has been deprecated! Don't use it anymore!
4352
4744
 
@@ -4400,7 +4792,7 @@ EOT
4400
4792
  def rule_scenarioIdCol
4401
4793
  pattern(%w( $ID_WITH_COLON ), lambda {
4402
4794
  if (@scenarioIdx = @project.scenarioIdx(@val[0])).nil?
4403
- error('unknown_scenario_id', "Unknown scenario: @val[0]",
4795
+ error('unknown_scenario_id', "Unknown scenario: #{@val[0]}",
4404
4796
  @sourceFileInfo[0])
4405
4797
  end
4406
4798
  })
@@ -4432,7 +4824,7 @@ EOT
4432
4824
  doc('shift', <<'EOT'
4433
4825
  A shift combines several workhours related settings in a reusable entity.
4434
4826
  Besides the weekly working hours it can also hold information such as
4435
- vacations and a time zone.
4827
+ leaves and a time zone.
4436
4828
 
4437
4829
  Shifts have a global name space. All IDs must be unique within the shifts of
4438
4830
  the project.
@@ -4444,27 +4836,23 @@ EOT
4444
4836
  def rule_shiftAssignment
4445
4837
  pattern(%w( !shiftId !intervalOptional ), lambda {
4446
4838
  # Make sure we have a ShiftAssignment for the property.
4447
- sa = @property['shifts', @scenarioIdx] || ShiftAssignments.new
4448
- sa.project = @project
4839
+ unless @shiftAssignments
4840
+ @shiftAssignments = ShiftAssignments.new
4841
+ @shiftAssignments.project = @project
4842
+ end
4449
4843
 
4450
4844
  if @val[1].nil?
4451
4845
  interval = TimeInterval.new(@project['start'], @project['end'])
4452
4846
  else
4453
4847
  interval = @val[1]
4454
4848
  end
4455
- if !sa.addAssignment(ShiftAssignment.new(@val[0].scenario(@scenarioIdx),
4456
- interval))
4849
+ if !@shiftAssignments.addAssignment(
4850
+ ShiftAssignment.new(@val[0].scenario(@scenarioIdx), interval))
4457
4851
  error('shift_assignment_overlap',
4458
4852
  'Shifts may not overlap each other.',
4459
4853
  @sourceFileInfo[0], @property)
4460
4854
  end
4461
- # Set same value again to set the 'provided' state for the attribute.
4462
- begin
4463
- @property['shifts', @scenarioIdx] = sa
4464
- rescue AttributeOverwrite
4465
- # Multiple shift assignments are a common idiom, so don't warn about
4466
- # them.
4467
- end
4855
+ @shiftAssignments.assignments.last
4468
4856
  })
4469
4857
  end
4470
4858
 
@@ -4513,11 +4901,22 @@ EOT
4513
4901
  end
4514
4902
 
4515
4903
  def rule_shiftScenarioAttributes
4904
+ pattern(%w( !leaves ), lambda {
4905
+ begin
4906
+ @property['leaves', @scenarioIdx] += @val[0]
4907
+ rescue AttributeOverwrite
4908
+ end
4909
+ })
4910
+
4516
4911
  pattern(%w( _replace ), lambda {
4517
4912
  @property['replace', @scenarioIdx] = true
4518
4913
  })
4519
4914
  doc('replace', <<'EOT'
4520
- Use this attribute if the vacation definition for the shift should replace the vacation settings of a resource. This is only effective for shifts that are assigned to resources directly. It is not effective for shifts that are assigned to tasks or allocations.
4915
+ This replace mode is only effective for shifts that are assigned to resources
4916
+ directly. When replace mode is activated the leave definitions of the shift
4917
+ will replace all the leave definitions of the resource for the given period.
4918
+
4919
+ The mode is not effective for shifts that are assigned to tasks or allocations.
4521
4920
  EOT
4522
4921
  )
4523
4922
 
@@ -4544,8 +4943,13 @@ EOT
4544
4943
  )
4545
4944
 
4546
4945
  pattern(%w( _vacation !vacationName !intervalsOptional ), lambda {
4547
- @property['vacations', @scenarioIdx] =
4548
- @property['vacations', @scenarioIdx ] + @val[2]
4946
+ begin
4947
+ @val[2].each do |interval|
4948
+ # We map the old 'vacation' attribute to public holidays.
4949
+ @property['leaves', @scenarioIdx] << Leave.new(:holiday, interval)
4950
+ end
4951
+ rescue AttributeOverwrite
4952
+ end
4549
4953
  })
4550
4954
  doc('vacation.shift', <<'EOT'
4551
4955
  Specify a vacation period associated with this shift.
@@ -4640,6 +5044,19 @@ EOT
4640
5044
  )
4641
5045
  end
4642
5046
 
5047
+ def rule_sortAccounts
5048
+ pattern(%w( _sortaccounts !sortCriteria ), lambda {
5049
+ @property.set('sortAccounts', @val[1])
5050
+ })
5051
+ doc('sortaccounts', <<'EOT'
5052
+ Determines how the accounts are sorted in the report. Multiple criteria can be
5053
+ specified as a comma separated list. If one criteria is not sufficient to sort
5054
+ a group of accounts, the next criteria will be used to sort the accounts in
5055
+ this group.
5056
+ EOT
5057
+ )
5058
+ end
5059
+
4643
5060
  def rule_sortResources
4644
5061
  pattern(%w( _sortresources !sortCriteria ), lambda {
4645
5062
  @property.set('sortResources', @val[1])
@@ -4680,27 +5097,23 @@ EOT
4680
5097
  end
4681
5098
  def rule_ssReportHeader
4682
5099
  pattern(%w( _statussheetreport !optionalID $STRING ), lambda {
4683
- if (fileName = @val[2]) != '.'
4684
- if @project.reports[fileName]
4685
- error('report_redefinition',
4686
- "A report with the name '#{fileName}' has already been " +
4687
- "defined.", @sourceFileInfo[2])
4688
- end
4689
- else
4690
- fileName = "statusSheet#{@project.reports.length + 1}"
5100
+ newReport(@val[1], @val[2], :statusSheet, @sourceFileInfo[0])
5101
+ @property.set('formats', [ :tjp ])
5102
+
5103
+ unless @project.scenario(0).get('active')
5104
+ @property.set('scenarios', [ 0 ])
4691
5105
  end
4692
- report = newReport(@val[1], fileName, :statusSheet, @sourceFileInfo[0])
4693
- report.set('scenarios', [ 0 ])
4694
5106
  # Show all tasks, sorted by id-up.
4695
- report.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
4696
- report.set('sortTasks', [ [ 'id', true, -1 ] ])
5107
+ @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
5108
+ @property.set('sortTasks', [ [ 'id', true, -1 ] ])
4697
5109
  # Show all resources, sorted by seqno-up.
4698
- report.set('hideResource', LogicalExpression.new(LogicalOperation.new(0)))
4699
- report.set('sortResources', [ [ 'seqno', true, -1 ] ])
4700
- report.set('loadUnit', :hours)
4701
- report.set('definitions', [])
5110
+ @property.set('hideResource',
5111
+ LogicalExpression.new(LogicalOperation.new(0)))
5112
+ @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
5113
+ @property.set('loadUnit', :hours)
5114
+ @property.set('definitions', [])
4702
5115
  })
4703
- arg(1, 'file name', <<'EOT'
5116
+ arg(2, 'file name', <<'EOT'
4704
5117
  The name of the status sheet report file to generate. It must end with a .tji
4705
5118
  extension, or use . to use the standard output channel.
4706
5119
  EOT
@@ -4759,7 +5172,7 @@ EOT
4759
5172
  @sourceFileInfo[0])
4760
5173
  @journalEntry.alertLevel = @val[1]
4761
5174
  @journalEntry.author = @sheetAuthor
4762
-
5175
+ @journalEntry.moderators << @sheetModerator
4763
5176
  })
4764
5177
  end
4765
5178
 
@@ -4812,8 +5225,18 @@ EOT
4812
5225
  'No trackingscenario defined.')
4813
5226
  end
4814
5227
  @sheetAuthor = @val[1]
5228
+ @sheetModerator = @val[1]
4815
5229
  @sheetStart = @val[2].start
4816
5230
  @sheetEnd = @val[2].end
5231
+ # Make sure that we don't have any status sheet entries from the same
5232
+ # author for the same report period. There may have been a previous
5233
+ # submission of the same report and this is an update to it. All old
5234
+ # entries must be removed before we process the sheet.
5235
+ @project['journal'].delete_if do |e|
5236
+ # Journal entries from status sheets have the sheet end date as entry
5237
+ # date.
5238
+ e.moderators.include?(@sheetModerator) && e.date == @sheetEnd
5239
+ end
4817
5240
  })
4818
5241
  arg(1, 'reporter', <<'EOT'
4819
5242
  The ID of a defined resource. This identifies the status reporter. Unless the
@@ -4941,7 +5364,7 @@ EOT
4941
5364
  pattern(%w( _report !reportId ), lambda {
4942
5365
  @property = @val[1]
4943
5366
  })
4944
- arg(1, 'report ID', 'The ID of an already defined report.')
5367
+ arg(1, 'report ID', 'The absolute ID of an already defined report.')
4945
5368
  end
4946
5369
 
4947
5370
  def rule_supplementResource
@@ -4955,7 +5378,7 @@ EOT
4955
5378
  pattern(%w( _task !taskId ), lambda {
4956
5379
  @property = @val[1]
4957
5380
  })
4958
- arg(1, 'task ID', 'The ID of an already defined task.')
5381
+ arg(1, 'task ID', 'The absolute ID of an already defined task.')
4959
5382
  end
4960
5383
 
4961
5384
  def rule_tagfile
@@ -4973,16 +5396,16 @@ EOT
4973
5396
 
4974
5397
  def rule_tagfileHeader
4975
5398
  pattern(%w( _tagfile !optionalID $STRING ), lambda {
4976
- report = newReport(@val[1], @val[2], :tagfile, @sourceFileInfo[0])
4977
-
5399
+ newReport(@val[1], @val[2], :tagfile, @sourceFileInfo[0])
4978
5400
  @property.set('formats', [ :ctags ])
5401
+
4979
5402
  # Include all tasks.
4980
- report.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
4981
- report.set('sortTasks', [ [ 'seqno', true, -1 ] ])
5403
+ @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
5404
+ @property.set('sortTasks', [ [ 'seqno', true, -1 ] ])
4982
5405
  # Include all resources.
4983
- report.set('hideResource',
4984
- LogicalExpression.new(LogicalOperation.new(0)))
4985
- report.set('sortResources', [ [ 'seqno', true, -1 ] ])
5406
+ @property.set('hideResource',
5407
+ LogicalExpression.new(LogicalOperation.new(0)))
5408
+ @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
4986
5409
  })
4987
5410
  arg(2, 'file name', <<'EOT'
4988
5411
  The name of the tagfile to generate. You can leave it empty and it will
@@ -5032,6 +5455,7 @@ EOT
5032
5455
  @property.adopt(task)
5033
5456
  end
5034
5457
  })
5458
+ level(:experimental)
5035
5459
  doc('adopt.task', <<'EOT'
5036
5460
  Add a previously defined task to the sub-tasks of this task. This can be used
5037
5461
  to create virtual sub projects that contain of task trees that were defined as
@@ -5039,10 +5463,7 @@ sub tasks of other tasks. Adopted tasks don't inherit anything from their step
5039
5463
  parents. However, the adopting task is scheduled to fit all adopted childs as
5040
5464
  well.
5041
5465
 
5042
- The adopting task and the adopted task must not share a common top-level task.
5043
- Adopted tasks may not have overlaping sub trees.
5044
-
5045
- '''This feature is experimental right now. Don't use it!'''.
5466
+ A top-level tasks must never include the same task more than once.
5046
5467
  EOT
5047
5468
  )
5048
5469
 
@@ -5135,7 +5556,7 @@ Specifies the minimum required gap between the end of a preceding task and the
5135
5556
  start of this task, or the start of a following task and the end of this task.
5136
5557
  This is working time, not calendar time. 7d means 7 working days, not one
5137
5558
  week. Whether a day is considered a working day or not depends on the defined
5138
- working hours and global vacations.
5559
+ working hours and global leaves.
5139
5560
  EOT
5140
5561
  )
5141
5562
 
@@ -5285,15 +5706,65 @@ EOT
5285
5706
  })
5286
5707
  end
5287
5708
 
5288
- def rule_taskScenarioAttributes
5289
-
5290
- pattern(%w( _account $ID ), lambda {
5291
- # TODO
5709
+ def rule_taskReport
5710
+ pattern(%w( !taskReportHeader !reportBody ), lambda {
5711
+ @property = @property.parent
5292
5712
  })
5293
- doc('account.task', <<'EOT'
5294
- This property has been deprecated. Use [[charge]] instead.
5713
+ doc('taskreport', <<'EOT'
5714
+ The report lists tasks and their respective values in a table. To reduce the
5715
+ list of included tasks, you can use the [[hidetask]], [[rolluptask]] or
5716
+ [[taskroot]] attributes. The order of the task can be controlled with
5717
+ [[sorttasks]]. If the first sorting criteria is tree sorting, the parent tasks
5718
+ will always be included to form the tree. Tree sorting is the default. You
5719
+ need to change it if you do not want certain parent tasks to be included in
5720
+ the report.
5721
+
5722
+ The resources that are allocated to each task can be listed as well. Use the
5723
+ [[hideresource]] attribute for this.
5295
5724
  EOT
5296
- )
5725
+ )
5726
+ example('HtmlTaskReport')
5727
+ end
5728
+
5729
+ def rule_taskReportHeader
5730
+ pattern(%w( _taskreport !optionalID !reportName ), lambda {
5731
+ newReport(@val[1], @val[2], :taskreport, @sourceFileInfo[0])
5732
+
5733
+ unless @property.modified?('columns')
5734
+ # Set the default columns for this report.
5735
+ %w( bsi name start end effort chart ).each do |col|
5736
+ @property.get('columns') <<
5737
+ TableColumnDefinition.new(col, columnTitle(col))
5738
+ end
5739
+ end
5740
+ # Show all tasks, sorted by tree, start-up, seqno-up.
5741
+ unless @property.modified?('hideTask')
5742
+ @property.set('hideTask',
5743
+ LogicalExpression.new(LogicalOperation.new(0)))
5744
+ end
5745
+ unless @property.modified?('sortTasks')
5746
+ @property.set('sortTasks',
5747
+ [ [ 'tree', true, -1 ],
5748
+ [ 'start', true, 0 ],
5749
+ [ 'seqno', true, -1 ] ])
5750
+ end
5751
+ # Show no resources, but set sorting to id-up.
5752
+ unless @property.modified?('hideResource')
5753
+ @property.set('hideResource',
5754
+ LogicalExpression.new(LogicalOperation.new(1)))
5755
+ end
5756
+ unless @property.modified?('sortResources')
5757
+ @property.set('sortResources', [ [ 'id', true, -1 ] ])
5758
+ end
5759
+ })
5760
+ end
5761
+
5762
+ def rule_taskScenarioAttributes
5763
+
5764
+ pattern(%w( _account $ID ))
5765
+ level(:removed)
5766
+ also('chargeset')
5767
+ doc('account.task', '')
5297
5768
 
5298
5769
  pattern(%w( !allocate ))
5299
5770
 
@@ -5381,10 +5852,13 @@ EOT
5381
5852
  })
5382
5853
  doc('complete', <<'EOT'
5383
5854
  Specifies what percentage of the task is already completed. This can be useful
5384
- for project tracking. Reports with calendar elements may show the completed
5385
- part of the task in a different color. The completion percentage has no impact
5386
- on the scheduler. It's meant for documentation purposes only.
5387
- Tasks may not have subtasks if this attribute is used.
5855
+ for simple progress tracking like in a TODO list. The provided completion
5856
+ degree is used for the ''''complete'''' and ''''gauge'''' columns in reports.
5857
+ Reports with calendar elements may show the completed part of the task in a
5858
+ different color.
5859
+
5860
+ The completion percentage has no impact on the scheduler. It's meant for
5861
+ documentation purposes only.
5388
5862
  EOT
5389
5863
  )
5390
5864
  example('Complete', '1')
@@ -5479,12 +5953,13 @@ EOT
5479
5953
  @property['charge', @scenarioIdx] +
5480
5954
  [ Charge.new(@val[1], :onEnd, @property, @scenarioIdx) ]
5481
5955
  })
5956
+ level(:deprecated)
5482
5957
  doc('endcredit', <<'EOT'
5483
5958
  Specifies an amount that is credited to the accounts specified by the
5484
- [[chargeset]] attributes at the moment the tasks ends. This attribute has been
5485
- deprecated and should no longer be used. Use [[charge]] instead.
5959
+ [[chargeset]] attributes at the moment the tasks ends.
5486
5960
  EOT
5487
5961
  )
5962
+ also('charge')
5488
5963
  example('Account', '1')
5489
5964
  pattern(%w( !flags ))
5490
5965
  doc('flags.task', <<'EOT'
@@ -5511,7 +5986,7 @@ is available is still considered working time, if there is no global vacation
5511
5986
  and global working hours are defined accordingly.
5512
5987
 
5513
5988
  For the length calculation, only the global working hours and the global
5514
- vacations matter. If a resource has additinal working hours defined, it's
5989
+ leaves matter. If a resource has additinal working hours defined, it's
5515
5990
  quite possible that a task with a length of 5d will have an allocated effort
5516
5991
  larger than 40 hours. Resource working hours only have an impact on whether an
5517
5992
  allocation is made or not for a particular time slot. They don't effect the
@@ -5593,12 +6068,13 @@ EOT
5593
6068
  @property['charge', @scenarioIdx] +=
5594
6069
  [ Charge.new(@val[1], :onStart, @property, @scenarioIdx) ]
5595
6070
  })
6071
+ level(:deprecated)
5596
6072
  doc('startcredit', <<'EOT'
5597
6073
  Specifies an amount that is credited to the account specified by the
5598
- [[chargeset]] attributes at the moment the tasks starts. This attribute has
5599
- been deprecated and should no longer be used. Use [[charge]] instead.
6074
+ [[chargeset]] attributes at the moment the tasks starts.
5600
6075
  EOT
5601
6076
  )
6077
+ also('charge')
5602
6078
  pattern(%w( !taskPeriod ))
5603
6079
 
5604
6080
  pattern(%w( _precedes !taskPredList ), lambda {
@@ -5742,17 +6218,34 @@ end attribute comes after the start attribute.
5742
6218
  EOT
5743
6219
  )
5744
6220
 
5745
- pattern(%w( _shift !shiftAssignments ), lambda {
6221
+ pattern(%w( !taskShiftAssignments !shiftAssignments ), lambda {
5746
6222
  checkContainer('shift')
6223
+ # Set same value again to set the 'provided' state for the attribute.
6224
+ begin
6225
+ @property['shifts', @scenarioIdx] = @shiftAssignments
6226
+ rescue AttributeOverwrite
6227
+ # Multiple shift assignments are a common idiom, so don't warn about
6228
+ # them.
6229
+ end
6230
+ @shiftAssignments = nil
5747
6231
  })
6232
+ level(:deprecated)
5748
6233
  doc('shift.task', <<'EOT'
5749
6234
  This keyword has been deprecated. Please use [[shifts.task|shifts
5750
6235
  (task)]] instead.
5751
6236
  EOT
5752
6237
  )
6238
+ also('shifts.task')
5753
6239
 
5754
- pattern(%w( _shifts !shiftAssignments ), lambda {
6240
+ pattern(%w( !taskShiftsAssignments !shiftAssignments ), lambda {
5755
6241
  checkContainer('shifts')
6242
+ begin
6243
+ @property['shifts', @scenarioIdx] = @shiftAssignments
6244
+ rescue AttributeOverwrite
6245
+ # Multiple shift assignments are a common idiom, so don't warn about
6246
+ # them.
6247
+ end
6248
+ @shiftAssignments = nil
5756
6249
  })
5757
6250
  doc('shifts.task', <<'EOT'
5758
6251
  Limits the working time for this task during the during the specified interval
@@ -5790,6 +6283,37 @@ EOT
5790
6283
  # Other attributes will be added automatically.
5791
6284
  end
5792
6285
 
6286
+ def rule_taskShiftAssignments
6287
+ pattern(%w( _shift ), lambda {
6288
+ @shiftAssignments = @property['shifts', @scenarioIdx]
6289
+ })
6290
+ end
6291
+
6292
+ def rule_taskShiftsAssignments
6293
+ pattern(%w( _shifts ), lambda {
6294
+ @shiftAssignments = @property['shifts', @scenarioIdx]
6295
+ })
6296
+ end
6297
+
6298
+ def rule_textReport
6299
+ pattern(%w( !textReportHeader !reportBody ), lambda {
6300
+ @property = @property.parent
6301
+ })
6302
+ doc('textreport', <<'EOT'
6303
+ This report consists of 5 RichText sections, a header, a center section with a
6304
+ left and right margin and a footer. The sections may contain the output of
6305
+ other defined reports.
6306
+ EOT
6307
+ )
6308
+ example('textreport')
6309
+ end
6310
+
6311
+ def rule_textReportHeader
6312
+ pattern(%w( _textreport !optionalID !reportName ), lambda {
6313
+ newReport(@val[1], @val[2], :textreport, @sourceFileInfo[0])
6314
+ })
6315
+ end
6316
+
5793
6317
  def rule_timeformat
5794
6318
  pattern(%w( _timeformat $STRING ), lambda {
5795
6319
  @val[1]
@@ -6009,7 +6533,7 @@ EOT
6009
6533
  doc('shift.timesheet', <<'EOT'
6010
6534
  Specifies an alternative [[shift]] for the time sheet period. This shift will
6011
6535
  override any existing working hour definitions for the resource. It will not
6012
- override already declared [[vacation|vacations]] though.
6536
+ override already declared [[leaves]] though.
6013
6537
 
6014
6538
  The primary use of this feature is to let the resources report different total
6015
6539
  work time for the report period.
@@ -6118,19 +6642,23 @@ EOT
6118
6642
  end
6119
6643
  def rule_tsReportHeader
6120
6644
  pattern(%w( _timesheetreport !optionalID $STRING ), lambda {
6121
- report = newReport(@val[1], @val[2], :timeSheet, @sourceFileInfo[0])
6645
+ newReport(@val[1], @val[2], :timeSheet, @sourceFileInfo[0])
6646
+ @property.set('formats', [ :tjp ])
6122
6647
 
6123
- report.set('scenarios', [ 0 ])
6648
+ unless @project.scenario(0).get('active')
6649
+ @property.set('scenarios', [ 0 ])
6650
+ end
6124
6651
  # Show all tasks, sorted by seqno-up.
6125
- report.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
6126
- report.set('sortTasks', [ [ 'seqno', true, -1 ] ])
6652
+ @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
6653
+ @property.set('sortTasks', [ [ 'seqno', true, -1 ] ])
6127
6654
  # Show all resources, sorted by seqno-up.
6128
- report.set('hideResource', LogicalExpression.new(LogicalOperation.new(0)))
6129
- report.set('sortResources', [ [ 'seqno', true, -1 ] ])
6130
- report.set('loadUnit', :hours)
6131
- report.set('definitions', [])
6655
+ @property.set('hideResource',
6656
+ LogicalExpression.new(LogicalOperation.new(0)))
6657
+ @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
6658
+ @property.set('loadUnit', :hours)
6659
+ @property.set('definitions', [])
6132
6660
  })
6133
- arg(1, 'file name', <<'EOT'
6661
+ arg(2, 'file name', <<'EOT'
6134
6662
  The name of the time sheet report file to generate. It must end with a .tji
6135
6663
  extension, or use . to use the standard output channel.
6136
6664
  EOT
@@ -6319,7 +6847,7 @@ EOT
6319
6847
  def rule_vacationName
6320
6848
  optional
6321
6849
  pattern(%w( $STRING )) # We just throw the name away
6322
- arg(0, 'name', 'An optional name for the vacation')
6850
+ arg(0, 'name', 'An optional name or reason for the leave')
6323
6851
  end
6324
6852
 
6325
6853
  def rule_valDate
@@ -6478,7 +7006,7 @@ EOT
6478
7006
  60 * 60, # hours
6479
7007
  60 * 60 * @project['dailyworkinghours'], # days
6480
7008
  60 * 60 * @project['dailyworkinghours'] *
6481
- (@project['yearlyworkingdays'] / 52.1429), # weeks
7009
+ (@project.weeklyWorkingDays), # weeks
6482
7010
  60 * 60 * @project['dailyworkinghours'] *
6483
7011
  (@project['yearlyworkingdays'] / 12), # months
6484
7012
  60 * 60 * @project['dailyworkinghours'] *