taskjuggler 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +160 -0
- data/benchmarks/UTF-8-Strings.rb +58 -0
- data/data/css/tjreport.css +7 -2
- data/doc/AppConfig.html +10 -4
- data/doc/Arguments.html +10 -4
- data/doc/CHANGELOG.html +171 -5
- data/doc/COPYING.html +10 -4
- data/doc/Object.html +11 -107
- data/doc/README.html +10 -4
- data/doc/RuntimeConfig.html +10 -4
- data/doc/String.html +16 -11
- data/doc/StringIO.html +10 -4
- data/doc/TaskJuggler.html +506 -435
- data/doc/TaskJuggler/Account.html +10 -4
- data/doc/TaskJuggler/AccountAttribute.html +10 -4
- data/doc/TaskJuggler/AccountScenario.html +10 -4
- data/doc/TaskJuggler/Allocation.html +69 -60
- data/doc/TaskJuggler/AllocationAttribute.html +10 -4
- data/doc/TaskJuggler/AttributeBase.html +10 -4
- data/doc/TaskJuggler/AttributeDefinition.html +10 -4
- data/doc/TaskJuggler/BatchProcessor.html +202 -192
- data/doc/TaskJuggler/Booking.html +10 -4
- data/doc/TaskJuggler/BookingListAttribute.html +10 -4
- data/doc/TaskJuggler/BooleanAttribute.html +10 -4
- data/doc/TaskJuggler/CSVFile.html +10 -4
- data/doc/TaskJuggler/CellSettingPattern.html +10 -4
- data/doc/TaskJuggler/CellSettingPatternList.html +10 -4
- data/doc/TaskJuggler/Charge.html +10 -4
- data/doc/TaskJuggler/ChargeListAttribute.html +10 -4
- data/doc/TaskJuggler/ChargeSet.html +10 -4
- data/doc/TaskJuggler/ChargeSetListAttribute.html +10 -4
- data/doc/TaskJuggler/ColumnListAttribute.html +10 -4
- data/doc/TaskJuggler/ColumnTable.html +10 -4
- data/doc/TaskJuggler/Daemon.html +71 -52
- data/doc/TaskJuggler/DateAttribute.html +10 -4
- data/doc/TaskJuggler/DefinitionListAttribute.html +10 -4
- data/doc/TaskJuggler/DependencyListAttribute.html +10 -4
- data/doc/TaskJuggler/DurationAttribute.html +10 -4
- data/doc/TaskJuggler/{MacroParser.html → FileList.html} +58 -173
- data/doc/TaskJuggler/{RichTextException.html → FileRecord.html} +59 -80
- data/doc/TaskJuggler/FixnumAttribute.html +10 -4
- data/doc/TaskJuggler/FlagListAttribute.html +10 -4
- data/doc/TaskJuggler/FloatAttribute.html +10 -4
- data/doc/TaskJuggler/FormatListAttribute.html +10 -4
- data/doc/TaskJuggler/GanttChart.html +10 -4
- data/doc/TaskJuggler/GanttContainer.html +14 -8
- data/doc/TaskJuggler/GanttHeader.html +10 -4
- data/doc/TaskJuggler/GanttHeaderScaleItem.html +10 -4
- data/doc/TaskJuggler/GanttLine.html +29 -24
- data/doc/TaskJuggler/GanttLoadStack.html +10 -4
- data/doc/TaskJuggler/GanttMilestone.html +10 -4
- data/doc/TaskJuggler/GanttRouter.html +10 -4
- data/doc/TaskJuggler/GanttTaskBar.html +20 -10
- data/doc/TaskJuggler/HTMLDocument.html +10 -4
- data/doc/TaskJuggler/HTMLGraphics.html +10 -4
- data/doc/TaskJuggler/Interval.html +10 -4
- data/doc/TaskJuggler/IntervalListAttribute.html +10 -4
- data/doc/TaskJuggler/JobInfo.html +10 -4
- data/doc/TaskJuggler/Journal.html +227 -160
- data/doc/TaskJuggler/JournalEntry.html +10 -4
- data/doc/TaskJuggler/JournalEntryList.html +158 -72
- data/doc/TaskJuggler/KeywordArray.html +21 -9
- data/doc/TaskJuggler/KeywordDocumentation.html +612 -475
- data/doc/TaskJuggler/Limits.html +13 -8
- data/doc/TaskJuggler/Limits/Limit.html +10 -4
- data/doc/TaskJuggler/LimitsAttribute.html +10 -4
- data/doc/TaskJuggler/ListAttributeBase.html +10 -4
- data/doc/TaskJuggler/Log.html +10 -4
- data/doc/TaskJuggler/LogFile.html +10 -4
- data/doc/TaskJuggler/LogicalAttribute.html +10 -4
- data/doc/TaskJuggler/LogicalExpression.html +11 -5
- data/doc/TaskJuggler/LogicalExpressionAttribute.html +10 -4
- data/doc/TaskJuggler/LogicalFlag.html +10 -4
- data/doc/TaskJuggler/LogicalFunction.html +132 -124
- data/doc/TaskJuggler/LogicalOperation.html +10 -4
- data/doc/TaskJuggler/Macro.html +16 -10
- data/doc/TaskJuggler/MacroTable.html +44 -38
- data/doc/TaskJuggler/ManagerResponsibilities.html +10 -4
- data/doc/TaskJuggler/ManagerStatusRecord.html +10 -4
- data/doc/TaskJuggler/Message.html +92 -68
- data/doc/TaskJuggler/MessageHandler.html +349 -28
- data/doc/TaskJuggler/Navigator.html +10 -4
- data/doc/TaskJuggler/NavigatorElement.html +10 -4
- data/doc/TaskJuggler/NikuProject.html +10 -4
- data/doc/TaskJuggler/NikuReport.html +10 -4
- data/doc/TaskJuggler/NikuResource.html +10 -4
- data/doc/TaskJuggler/NodeListAttribute.html +10 -4
- data/doc/TaskJuggler/OnShiftCache.html +10 -4
- data/doc/TaskJuggler/ProcessIntercom.html +118 -111
- data/doc/TaskJuggler/ProcessIntercomIface.html +75 -22
- data/doc/TaskJuggler/Project.html +886 -913
- data/doc/TaskJuggler/ProjectBroker.html +442 -331
- data/doc/TaskJuggler/ProjectBrokerIface.html +95 -38
- data/doc/TaskJuggler/ProjectFileParser.html +320 -317
- data/doc/TaskJuggler/ProjectFileScanner.html +336 -339
- data/doc/TaskJuggler/ProjectRecord.html +119 -56
- data/doc/TaskJuggler/ProjectServer.html +282 -237
- data/doc/TaskJuggler/ProjectServerIface.html +45 -39
- data/doc/TaskJuggler/PropertyAttribute.html +10 -4
- data/doc/TaskJuggler/PropertyList.html +177 -173
- data/doc/TaskJuggler/PropertySet.html +11 -5
- data/doc/TaskJuggler/PropertyTreeNode.html +194 -191
- data/doc/TaskJuggler/Query.html +280 -256
- data/doc/TaskJuggler/RTFHandlers.html +10 -4
- data/doc/TaskJuggler/RTFNavigator.html +33 -26
- data/doc/TaskJuggler/RTFQuery.html +135 -169
- data/doc/TaskJuggler/RTFReport.html +63 -56
- data/doc/TaskJuggler/RTFReportLink.html +58 -47
- data/doc/TaskJuggler/RTFWithQuerySupport.html +666 -0
- data/doc/TaskJuggler/RealFormat.html +10 -4
- data/doc/TaskJuggler/RealFormatAttribute.html +10 -4
- data/doc/TaskJuggler/ReferenceAttribute.html +10 -4
- data/doc/TaskJuggler/Report.html +333 -290
- data/doc/TaskJuggler/ReportBase.html +182 -174
- data/doc/TaskJuggler/ReportContext.html +10 -4
- data/doc/TaskJuggler/ReportServer.html +144 -126
- data/doc/TaskJuggler/ReportServerIface.html +50 -44
- data/doc/TaskJuggler/ReportServerRecord.html +38 -32
- data/doc/TaskJuggler/ReportServlet.html +144 -137
- data/doc/TaskJuggler/ReportTable.html +10 -4
- data/doc/TaskJuggler/ReportTableCell.html +169 -164
- data/doc/TaskJuggler/ReportTableColumn.html +10 -4
- data/doc/TaskJuggler/ReportTableLegend.html +10 -4
- data/doc/TaskJuggler/ReportTableLine.html +10 -4
- data/doc/TaskJuggler/Resource.html +121 -115
- data/doc/TaskJuggler/ResourceListAttribute.html +10 -4
- data/doc/TaskJuggler/ResourceListRE.html +10 -4
- data/doc/TaskJuggler/ResourceScenario.html +13 -7
- data/doc/TaskJuggler/RichText.html +61 -37
- data/doc/TaskJuggler/RichTextAttribute.html +10 -4
- data/doc/TaskJuggler/RichTextDocument.html +91 -81
- data/doc/TaskJuggler/RichTextElement.html +378 -317
- data/doc/TaskJuggler/RichTextFunctionExample.html +10 -4
- data/doc/TaskJuggler/RichTextFunctionHandler.html +16 -11
- data/doc/TaskJuggler/RichTextImage.html +10 -4
- data/doc/TaskJuggler/RichTextIntermediate.html +138 -70
- data/doc/TaskJuggler/RichTextParser.html +48 -40
- data/doc/TaskJuggler/RichTextScanner.html +328 -906
- data/doc/TaskJuggler/RichTextSnip.html +59 -57
- data/doc/TaskJuggler/RichTextSyntaxRules.html +458 -369
- data/doc/TaskJuggler/Scenario.html +10 -4
- data/doc/TaskJuggler/ScenarioData.html +33 -30
- data/doc/TaskJuggler/ScenarioListAttribute.html +10 -4
- data/doc/TaskJuggler/Scoreboard.html +10 -4
- data/doc/TaskJuggler/SheetHandlerBase.html +315 -191
- data/doc/TaskJuggler/SheetReceiver.html +334 -313
- data/doc/TaskJuggler/SheetSender.html +10 -4
- data/doc/TaskJuggler/Shift.html +10 -4
- data/doc/TaskJuggler/ShiftAssignment.html +10 -4
- data/doc/TaskJuggler/ShiftAssignments.html +10 -4
- data/doc/TaskJuggler/ShiftAssignmentsAttribute.html +10 -4
- data/doc/TaskJuggler/ShiftScenario.html +10 -4
- data/doc/TaskJuggler/SimpleQueryExpander.html +697 -0
- data/doc/TaskJuggler/SortListAttribute.html +10 -4
- data/doc/TaskJuggler/SourceFileInfo.html +10 -4
- data/doc/TaskJuggler/StatusSheetReceiver.html +10 -4
- data/doc/TaskJuggler/StatusSheetReport.html +10 -4
- data/doc/TaskJuggler/StatusSheetSender.html +10 -4
- data/doc/TaskJuggler/StringAttribute.html +10 -4
- data/doc/TaskJuggler/SymbolAttribute.html +10 -4
- data/doc/TaskJuggler/SyntaxReference.html +260 -230
- data/doc/TaskJuggler/TOCEntry.html +99 -42
- data/doc/TaskJuggler/TSResourceRecord.html +10 -4
- data/doc/TaskJuggler/TSTaskRecord.html +10 -4
- data/doc/TaskJuggler/TableColumnDefinition.html +10 -4
- data/doc/TaskJuggler/TableOfContents.html +54 -12
- data/doc/TaskJuggler/TableReport.html +877 -872
- data/doc/TaskJuggler/Task.html +117 -68
- data/doc/TaskJuggler/TaskDependency.html +10 -4
- data/doc/TaskJuggler/TaskListAttribute.html +10 -4
- data/doc/TaskJuggler/TaskListRE.html +10 -4
- data/doc/TaskJuggler/TaskScenario.html +1681 -1563
- data/doc/TaskJuggler/TextFormatter.html +10 -4
- data/doc/TaskJuggler/TextParser.html +567 -534
- data/doc/TaskJuggler/TextParser/Pattern.html +128 -118
- data/doc/TaskJuggler/TextParser/Rule.html +26 -15
- data/doc/TaskJuggler/TextParser/StackElement.html +10 -4
- data/doc/TaskJuggler/TextParser/TextParserResultArray.html +22 -16
- data/doc/TaskJuggler/TextParser/TokenDoc.html +10 -4
- data/doc/TaskJuggler/TextReport.html +15 -6
- data/doc/TaskJuggler/TextScanner.html +319 -287
- data/doc/TaskJuggler/TextScanner/BufferStreamHandle.html +16 -10
- data/doc/TaskJuggler/TextScanner/FileStreamHandle.html +23 -17
- data/doc/TaskJuggler/TextScanner/MacroStackEntry.html +17 -11
- data/doc/TaskJuggler/TextScanner/StreamHandle.html +102 -96
- data/doc/TaskJuggler/TimeSheet.html +138 -175
- data/doc/TaskJuggler/TimeSheetReceiver.html +10 -4
- data/doc/TaskJuggler/TimeSheetRecord.html +65 -58
- data/doc/TaskJuggler/TimeSheetReport.html +47 -42
- data/doc/TaskJuggler/TimeSheetSender.html +10 -4
- data/doc/TaskJuggler/TimeSheetSummary.html +91 -83
- data/doc/TaskJuggler/TimeSheets.html +22 -16
- data/doc/TaskJuggler/Tj3AppBase.html +10 -4
- data/doc/TaskJuggler/Tj3Client.html +399 -365
- data/doc/TaskJuggler/Tj3Daemon.html +107 -94
- data/doc/TaskJuggler/Tj3SheetAppBase.html +10 -4
- data/doc/TaskJuggler/Tj3SsReceiver.html +10 -4
- data/doc/TaskJuggler/Tj3SsSender.html +10 -4
- data/doc/TaskJuggler/Tj3TsReceiver.html +10 -4
- data/doc/TaskJuggler/Tj3TsSender.html +10 -4
- data/doc/TaskJuggler/Tj3TsSummary.html +10 -4
- data/doc/TaskJuggler/TjException.html +10 -4
- data/doc/TaskJuggler/TjTime.html +145 -140
- data/doc/TaskJuggler/TjpExample.html +10 -4
- data/doc/TaskJuggler/TjpExportRE.html +122 -118
- data/doc/TaskJuggler/TjpSyntaxRules.html +4065 -4052
- data/doc/TaskJuggler/URLParameter.html +10 -4
- data/doc/TaskJuggler/UserManual.html +162 -155
- data/doc/TaskJuggler/VimSyntax.html +1028 -0
- data/doc/TaskJuggler/WebServer.html +45 -27
- data/doc/TaskJuggler/WorkingHours.html +10 -4
- data/doc/TaskJuggler/WorkingHoursAttribute.html +10 -4
- data/doc/TaskJuggler/XMLBlob.html +10 -4
- data/doc/TaskJuggler/XMLComment.html +10 -4
- data/doc/TaskJuggler/XMLDocument.html +10 -4
- data/doc/TaskJuggler/XMLElement.html +10 -4
- data/doc/TaskJuggler/XMLNamedText.html +10 -4
- data/doc/TaskJuggler/XMLText.html +10 -4
- data/doc/index.html +735 -677
- data/doc/lib/AccountScenario_rb.html +1 -1
- data/doc/lib/Account_rb.html +1 -1
- data/doc/lib/Allocation_rb.html +1 -1
- data/doc/lib/AppConfig_rb.html +1 -1
- data/doc/lib/AttributeBase_rb.html +1 -1
- data/doc/lib/AttributeDefinition_rb.html +1 -1
- data/doc/lib/Attributes_rb.html +1 -1
- data/doc/lib/BatchProcessor_rb.html +1 -1
- data/doc/lib/Booking_rb.html +1 -1
- data/doc/lib/ChargeSet_rb.html +1 -1
- data/doc/lib/Charge_rb.html +1 -1
- data/doc/lib/{Message_rb.html → FileList_rb.html} +3 -5
- data/doc/lib/HTMLDocument_rb.html +1 -1
- data/doc/lib/Interval_rb.html +1 -1
- data/doc/lib/Journal_rb.html +1 -1
- data/doc/lib/KeywordArray_rb.html +1 -1
- data/doc/lib/KeywordDocumentation_rb.html +1 -1
- data/doc/lib/Limits_rb.html +1 -1
- data/doc/lib/LogFile_rb.html +1 -1
- data/doc/lib/Log_rb.html +1 -1
- data/doc/lib/LogicalExpression_rb.html +1 -1
- data/doc/lib/LogicalFunction_rb.html +1 -1
- data/doc/lib/LogicalOperation_rb.html +1 -1
- data/doc/lib/MacroTable_rb.html +1 -3
- data/doc/lib/MessageHandler_rb.html +1 -1
- data/doc/lib/ProjectFileParser_rb.html +1 -1
- data/doc/lib/ProjectFileScanner_rb.html +1 -1
- data/doc/lib/Project_rb.html +4 -2
- data/doc/lib/PropertyList_rb.html +1 -1
- data/doc/lib/PropertySet_rb.html +1 -1
- data/doc/lib/PropertyTreeNode_rb.html +1 -1
- data/doc/lib/Query_rb.html +1 -1
- data/doc/lib/RTFHandlers_rb.html +1 -1
- data/doc/lib/RTFNavigator_rb.html +1 -1
- data/doc/lib/RTFQuery_rb.html +2 -2
- data/doc/lib/RTFReportLink_rb.html +4 -2
- data/doc/lib/RTFReport_rb.html +1 -1
- data/doc/lib/{MacroParser_rb.html → RTFWithQuerySupport_rb.html} +4 -6
- data/doc/lib/RealFormat_rb.html +1 -1
- data/doc/lib/ResourceScenario_rb.html +1 -1
- data/doc/lib/Resource_rb.html +1 -1
- data/doc/lib/RichTextDocument_rb.html +1 -1
- data/doc/lib/RichTextElement_rb.html +1 -1
- data/doc/lib/RichTextFunctionExample_rb.html +1 -1
- data/doc/lib/RichTextFunctionHandler_rb.html +1 -1
- data/doc/lib/RichTextParser_rb.html +1 -1
- data/doc/lib/RichTextScanner_rb.html +3 -1
- data/doc/lib/RichTextSnip_rb.html +1 -1
- data/doc/lib/RichTextSyntaxRules_rb.html +1 -1
- data/doc/lib/RichText_rb.html +3 -1
- data/doc/lib/RuntimeConfig_rb.html +1 -1
- data/doc/lib/ScenarioData_rb.html +2 -2
- data/doc/lib/Scenario_rb.html +1 -1
- data/doc/lib/Scoreboard_rb.html +1 -1
- data/doc/lib/SheetHandlerBase_rb.html +5 -1
- data/doc/lib/SheetReceiver_rb.html +3 -1
- data/doc/lib/SheetSender_rb.html +1 -1
- data/doc/lib/ShiftAssignments_rb.html +1 -1
- data/doc/lib/ShiftScenario_rb.html +1 -1
- data/doc/lib/Shift_rb.html +1 -1
- data/doc/lib/SimpleQueryExpander_rb.html +67 -0
- data/doc/lib/SourceFileInfo_rb.html +1 -1
- data/doc/lib/StatusSheetReceiver_rb.html +1 -1
- data/doc/lib/StatusSheetSender_rb.html +1 -1
- data/doc/lib/SyntaxReference_rb.html +1 -1
- data/doc/lib/TOCEntry_rb.html +1 -1
- data/doc/lib/TableColumnDefinition_rb.html +1 -1
- data/doc/lib/TableOfContents_rb.html +1 -1
- data/doc/lib/TaskDependency_rb.html +1 -1
- data/doc/lib/TaskJuggler_rb.html +1 -1
- data/doc/lib/TaskScenario_rb.html +1 -1
- data/doc/lib/Task_rb.html +1 -1
- data/doc/lib/TextFormatter_rb.html +1 -1
- data/doc/lib/TextParser/Pattern_rb.html +1 -1
- data/doc/lib/TextParser/Rule_rb.html +1 -1
- data/doc/lib/TextParser/StackElement_rb.html +1 -1
- data/doc/lib/TextParser/TokenDoc_rb.html +1 -1
- data/doc/lib/TextParser_rb.html +3 -1
- data/doc/lib/TextScanner_rb.html +1 -3
- data/doc/lib/TimeSheetReceiver_rb.html +1 -1
- data/doc/lib/TimeSheetSender_rb.html +1 -1
- data/doc/lib/TimeSheetSummary_rb.html +1 -1
- data/doc/lib/TimeSheets_rb.html +1 -1
- data/doc/lib/Tj3AppBase_rb.html +1 -1
- data/doc/lib/Tj3Config_rb.html +1 -1
- data/doc/lib/Tj3SheetAppBase_rb.html +1 -1
- data/doc/lib/TjException_rb.html +1 -1
- data/doc/lib/TjTime_rb.html +1 -1
- data/doc/lib/TjpExample_rb.html +1 -1
- data/doc/lib/TjpSyntaxRules_rb.html +1 -1
- data/doc/lib/URLParameter_rb.html +1 -1
- data/doc/lib/UTF8String_rb.html +1 -1
- data/doc/lib/UserManual_rb.html +1 -1
- data/doc/lib/{ruby-signal-bug_rb.html → VimSyntax_rb.html} +17 -4
- data/doc/lib/WorkingHours_rb.html +1 -1
- data/doc/lib/XMLDocument_rb.html +1 -1
- data/doc/lib/XMLElement_rb.html +1 -1
- data/doc/lib/daemon/Daemon_rb.html +1 -1
- data/doc/lib/daemon/ProcessIntercom_rb.html +1 -1
- data/doc/lib/daemon/ProjectBroker_rb.html +1 -1
- data/doc/lib/daemon/ProjectServer_rb.html +1 -1
- data/doc/lib/daemon/ReportServer_rb.html +1 -3
- data/doc/lib/daemon/WebServer_rb.html +1 -1
- data/doc/lib/deep_copy_rb.html +1 -1
- data/doc/lib/reports/CSVFile_rb.html +1 -1
- data/doc/lib/reports/ColumnTable_rb.html +1 -1
- data/doc/lib/reports/GanttChart_rb.html +1 -1
- data/doc/lib/reports/GanttContainer_rb.html +1 -1
- data/doc/lib/reports/GanttHeaderScaleItem_rb.html +1 -1
- data/doc/lib/reports/GanttHeader_rb.html +1 -1
- data/doc/lib/reports/GanttLine_rb.html +1 -1
- data/doc/lib/reports/GanttLoadStack_rb.html +1 -1
- data/doc/lib/reports/GanttMilestone_rb.html +1 -1
- data/doc/lib/reports/GanttRouter_rb.html +1 -1
- data/doc/lib/reports/GanttTaskBar_rb.html +1 -1
- data/doc/lib/reports/HTMLGraphics_rb.html +1 -1
- data/doc/lib/reports/Navigator_rb.html +1 -1
- data/doc/lib/reports/NikuReport_rb.html +1 -1
- data/doc/lib/reports/ReportBase_rb.html +1 -1
- data/doc/lib/reports/ReportContext_rb.html +1 -1
- data/doc/lib/reports/ReportTableCell_rb.html +1 -1
- data/doc/lib/reports/ReportTableColumn_rb.html +1 -1
- data/doc/lib/reports/ReportTableLegend_rb.html +1 -1
- data/doc/lib/reports/ReportTableLine_rb.html +1 -1
- data/doc/lib/reports/ReportTable_rb.html +1 -1
- data/doc/lib/reports/Report_rb.html +1 -1
- data/doc/lib/reports/ResourceListRE_rb.html +1 -1
- data/doc/lib/reports/StatusSheetReport_rb.html +1 -1
- data/doc/lib/reports/TableReport_rb.html +1 -1
- data/doc/lib/reports/TaskListRE_rb.html +1 -1
- data/doc/lib/reports/TextReport_rb.html +1 -1
- data/doc/lib/reports/TimeSheetReport_rb.html +1 -1
- data/doc/lib/reports/TjpExportRE_rb.html +1 -1
- data/doc/lib/taskjuggler3_rb.html +1 -1
- data/doc/lib/tj3client_rb.html +1 -1
- data/doc/lib/tj3d_rb.html +1 -1
- data/doc/lib/tj3man_rb.html +1 -1
- data/doc/lib/tj3ss_receiver_rb.html +1 -1
- data/doc/lib/tj3ss_sender_rb.html +1 -1
- data/doc/lib/tj3ts_receiver_rb.html +1 -1
- data/doc/lib/tj3ts_sender_rb.html +1 -1
- data/doc/lib/tj3ts_summary_rb.html +1 -1
- data/lib/Allocation.rb +8 -5
- data/lib/BatchProcessor.rb +7 -3
- data/lib/FileList.rb +58 -0
- data/lib/Journal.rb +73 -33
- data/lib/KeywordArray.rb +4 -0
- data/lib/KeywordDocumentation.rb +45 -11
- data/lib/Limits.rb +0 -1
- data/lib/LogicalExpression.rb +1 -1
- data/lib/LogicalFunction.rb +14 -12
- data/lib/MacroTable.rb +3 -4
- data/lib/MessageHandler.rb +136 -7
- data/lib/Project.rb +72 -86
- data/lib/ProjectFileParser.rb +30 -33
- data/lib/ProjectFileScanner.rb +7 -16
- data/lib/PropertyList.rb +25 -27
- data/lib/PropertySet.rb +1 -1
- data/lib/PropertyTreeNode.rb +9 -12
- data/lib/Query.rb +5 -4
- data/lib/RTFNavigator.rb +2 -1
- data/lib/RTFQuery.rb +4 -11
- data/lib/RTFReport.rb +2 -1
- data/lib/RTFReportLink.rb +10 -4
- data/lib/RTFWithQuerySupport.rb +45 -0
- data/lib/Resource.rb +20 -20
- data/lib/ResourceScenario.rb +3 -3
- data/lib/RichText.rb +15 -7
- data/lib/RichTextDocument.rb +8 -4
- data/lib/RichTextElement.rb +35 -12
- data/lib/RichTextFunctionHandler.rb +11 -12
- data/lib/RichTextParser.rb +5 -3
- data/lib/RichTextScanner.rb +144 -565
- data/lib/RichTextSnip.rb +3 -7
- data/lib/RichTextSyntaxRules.rb +51 -32
- data/lib/ScenarioData.rb +16 -25
- data/lib/SheetHandlerBase.rb +59 -2
- data/lib/SheetReceiver.rb +36 -18
- data/lib/SimpleQueryExpander.rb +58 -0
- data/lib/SyntaxReference.rb +9 -5
- data/lib/TOCEntry.rb +2 -0
- data/lib/TableOfContents.rb +4 -0
- data/lib/Task.rb +23 -12
- data/lib/TaskJuggler.rb +72 -33
- data/lib/TaskScenario.rb +131 -53
- data/lib/TextParser.rb +43 -30
- data/lib/TextParser/Pattern.rb +17 -13
- data/lib/TextParser/Rule.rb +5 -0
- data/lib/TextScanner.rb +46 -25
- data/lib/TimeSheetSummary.rb +9 -7
- data/lib/TimeSheets.rb +14 -23
- data/lib/Tj3Config.rb +1 -1
- data/lib/TjTime.rb +1 -2
- data/lib/TjpSyntaxRules.rb +128 -104
- data/lib/UTF8String.rb +0 -1
- data/lib/UserManual.rb +5 -4
- data/lib/VimSyntax.rb +223 -0
- data/lib/daemon/Daemon.rb +9 -0
- data/lib/daemon/ProcessIntercom.rb +19 -4
- data/lib/daemon/ProjectBroker.rb +149 -68
- data/lib/daemon/ProjectServer.rb +119 -79
- data/lib/daemon/ReportServer.rb +42 -31
- data/lib/daemon/WebServer.rb +21 -2
- data/lib/deep_copy.rb +1 -1
- data/lib/reports/GanttContainer.rb +2 -2
- data/lib/reports/GanttLine.rb +2 -3
- data/lib/reports/GanttTaskBar.rb +7 -3
- data/lib/reports/Report.rb +62 -57
- data/lib/reports/ReportBase.rb +6 -4
- data/lib/reports/ReportTableCell.rb +13 -14
- data/lib/reports/TableReport.rb +2 -1
- data/lib/reports/TextReport.rb +3 -0
- data/lib/reports/TimeSheetReport.rb +2 -3
- data/lib/reports/TjpExportRE.rb +0 -2
- data/lib/tj3client.rb +31 -3
- data/lib/tj3d.rb +8 -1
- data/manual/Day_To_Day_Juggling +2 -95
- data/manual/How_To_Contribute +2 -1
- data/manual/Rich_Text_Attributes +37 -3
- data/manual/Software +203 -0
- data/test/MessageChecker.rb +4 -4
- data/test/TestSuite/HTML-Reports/Alerts.html +172 -0
- data/test/TestSuite/HTML-Reports/CellText.html +758 -0
- data/test/TestSuite/HTML-Reports/ColumnPeriods.html +156 -0
- data/test/TestSuite/HTML-Reports/IsOngoing.html +172 -0
- data/test/TestSuite/HTML-Reports/LogicalFunctions.html +245 -0
- data/test/TestSuite/HTML-Reports/Query.html +31 -0
- data/test/TestSuite/HTML-Reports/css/tjmanual.css +14 -0
- data/test/TestSuite/HTML-Reports/css/tjreport.css +233 -21
- data/test/TestSuite/HTML-Reports/depArrows.html +842 -0
- data/test/TestSuite/HTML-Reports/scripts/scripts/wz_tooltip.js +1301 -0
- data/test/TestSuite/HTML-Reports/scripts/wz_tooltip.js +20 -20
- data/test/TestSuite/ReportGenerator/Correct/Alerts.tjp +48 -0
- data/test/TestSuite/ReportGenerator/Correct/Macros.tjp +57 -0
- data/test/TestSuite/ReportGenerator/Correct/refs/Alerts-1.csv +386 -0
- data/test/TestSuite/ReportGenerator/Correct/refs/Macros-1.csv +6 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/css/tjmanual.css +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/css/tjreport.css +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/details.png +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/flag-green.png +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/flag-red.png +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/flag-yellow.png +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/resource.png +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/resourcegroup.png +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/task.png +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/taskgroup.png +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/trend-down.png +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/trend-flat.png +0 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/icons/trend-up.png +0 -0
- data/test/TestSuite/ReportGenerator/Errors/rtp_report_recursion.html +26 -0
- data/test/TestSuite/ReportGenerator/{Correct → Errors}/scripts/wz_tooltip.js +0 -0
- data/test/TestSuite/Scheduler/Correct/Allocate.html +3210 -0
- data/test/TestSuite/Scheduler/Correct/Allocate.tjp +19 -0
- data/test/TestSuite/Scheduler/Correct/Container.html +22 -22
- data/test/TestSuite/Scheduler/Correct/Limits.html +4964 -0
- data/test/TestSuite/Scheduler/Correct/Shift.html +1707 -417
- data/test/TestSuite/Scheduler/Correct/Shift2.html +9 -9
- data/test/TestSuite/Scheduler/Correct/css/tjreport.css +6 -2
- data/test/TestSuite/Scheduler/Errors/css/tjmanual.css +66 -0
- data/test/TestSuite/Scheduler/Errors/css/tjreport.css +407 -0
- data/test/TestSuite/Scheduler/Errors/icons/details.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/flag-green.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/flag-red.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/flag-yellow.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/resource.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/resourcegroup.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/task.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/taskgroup.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/trend-down.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/trend-flat.png +0 -0
- data/test/TestSuite/Scheduler/Errors/icons/trend-up.png +0 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_1.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_10.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_11.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_12.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_13.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_14.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_2.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_3.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_4.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_5.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_6.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_7.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_8.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/loop_detected_9.tjp +1 -1
- data/test/TestSuite/Scheduler/Errors/scripts/wz_tooltip.js +1301 -0
- data/test/TestSuite/Scheduler/Errors/task_pred_before.tjp +11 -0
- data/test/TestSuite/Scheduler/Errors/task_pred_before_gd.tjp +11 -0
- data/test/TestSuite/Scheduler/Errors/task_pred_before_gl.tjp +11 -0
- data/test/TestSuite/Scheduler/Errors/task_succ_after.tjp +12 -0
- data/test/TestSuite/Scheduler/Errors/task_succ_after_gd.tjp +12 -0
- data/test/TestSuite/Scheduler/Errors/task_succ_after_gl.tjp +12 -0
- data/test/TestSuite/StatusSheets/dev2.tji +22 -0
- data/test/TestSuite/StatusSheets/resrep.tji +7 -0
- data/test/TestSuite/StatusSheets/run +6 -4
- data/test/TestSuite/StatusSheets/tj3d.log +312 -0
- data/test/TestSuite/Syntax/Correct/Managers.html +263 -0
- data/test/TestSuite/Syntax/Correct/tutorial.tjp +1 -2
- data/test/TestSuite/Syntax/Errors/empty.tjp +1 -1
- data/test/TestSuite/Syntax/Errors/macro_stack_overflow.tjp +1 -1
- data/test/TestSuite/TimeSheets/acceptable_intervals +1 -0
- data/test/TestSuite/TimeSheets/resrep.tji +7 -0
- data/test/TestSuite/TimeSheets/run +6 -5
- data/test/TestSuite/TimeSheets/statussheets.log +1 -0
- data/test/TestSuite/TimeSheets/ts.tji +351 -0
- data/test/TestSuite/TimeSheets/tsdef.tji +2 -0
- data/test/test_PropertySet.rb +2 -2
- data/test/test_RichText.rb +178 -387
- data/test/test_SimpleQueryExpander.rb +55 -0
- data/test/test_deep_copy.rb +2 -2
- metadata +854 -834
- data/lib/MacroParser.rb +0 -77
- data/lib/Message.rb +0 -56
- data/lib/ruby-signal-bug.rb +0 -43
- data/test/TestSuite/HTML-Reports/TimeSheet.html +0 -79
- data/test/TestSuite/HTML-Reports/reference.html +0 -51
- data/test/TestSuite/ReportGenerator/Correct/Journal.html +0 -63
- data/test/TestSuite/ReportGenerator/Correct/LogicalFunctions2.csv +0 -3
- data/test/TestSuite/ReportGenerator/Correct/opennodes.csv +0 -2
- data/test/TestSuite/ReportGenerator/Correct/opennodes.tjp +0 -26
- data/test/TestSuite/ReportGenerator/Correct/refs/opennodes-1.csv +0 -2
- data/test/TestSuite/Scheduler/Correct/Booking2.html +0 -603
- data/test/TestSuite/Scheduler/Correct/TimeSheet2.html +0 -108
- data/test/TestSuite/StatusSheetTemplates/project.tji +0 -35
- data/test/TestSuite/StatusSheetTemplates/project.tjp +0 -56
- data/test/TestSuite/Syntax/Correct/ResourcePrefix.html +0 -32
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env ruby -w
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
#
|
|
4
|
+
# = SimpleQueryExpander.rb -- The TaskJuggler III Project Management Software
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2006, 2007, 2008, 2009, 2010 by Chris Schlaeger <cs@kde.org>
|
|
7
|
+
#
|
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
|
10
|
+
# published by the Free Software Foundation.
|
|
11
|
+
#
|
|
12
|
+
|
|
13
|
+
require 'strscan'
|
|
14
|
+
|
|
15
|
+
class TaskJuggler
|
|
16
|
+
|
|
17
|
+
# The SimpleQueryExpander class is used to replace embedded attribute
|
|
18
|
+
# queries in a string with the value of the attribute. The embedded queries
|
|
19
|
+
# must have the form <-name-> where name is the name of the attribute. The
|
|
20
|
+
# Query class is used to determine the value of the attribute within the
|
|
21
|
+
# context of the query.
|
|
22
|
+
class SimpleQueryExpander
|
|
23
|
+
|
|
24
|
+
# _inputStr_ is the String with the embedded queries. _query_ is the Query
|
|
25
|
+
# with that provides the evaluation context. _messageHandle_ is a
|
|
26
|
+
# MessageHandler that will be used for error reporting. _sourceFileInfo_
|
|
27
|
+
# is a SourceFileInfo reference used for error reporting.
|
|
28
|
+
def initialize(inputStr, query, messageHandler, sourceFileInfo)
|
|
29
|
+
@inputStr = inputStr
|
|
30
|
+
@query = query.dup
|
|
31
|
+
@messageHandler = messageHandler
|
|
32
|
+
@sourceFileInfo = sourceFileInfo
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def expand
|
|
36
|
+
# Create a copy of the input string since we will modify it.
|
|
37
|
+
str = @inputStr.dup
|
|
38
|
+
# Replace all occurences of <-name->.
|
|
39
|
+
str.gsub!(/<-[a-zA-Z][_a-zA-Z]*->/) do |match|
|
|
40
|
+
len = match.size
|
|
41
|
+
attribute = match[2..-3]
|
|
42
|
+
@query.attributeId = attribute
|
|
43
|
+
@query.process
|
|
44
|
+
if @query.ok
|
|
45
|
+
@query.to_s
|
|
46
|
+
else
|
|
47
|
+
# The query failed. We report an error.
|
|
48
|
+
@messageHandler.error('sqe_expand_failed',
|
|
49
|
+
"Unknown attribute #{attribute}",
|
|
50
|
+
@sourceFileInfo)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
str
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
data/lib/SyntaxReference.rb
CHANGED
|
@@ -24,10 +24,14 @@ class TaskJuggler
|
|
|
24
24
|
# output as well as HTML files are supported.
|
|
25
25
|
class SyntaxReference
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
#
|
|
30
|
-
# then
|
|
27
|
+
attr_reader :keywords
|
|
28
|
+
|
|
29
|
+
# The constructor is the most important function of this class. It creates
|
|
30
|
+
# a parser object and then traverses all rules and extracts the documented
|
|
31
|
+
# patterns. In a second pass the extracted KeywordDocumentation objects
|
|
32
|
+
# are then cross referenced to capture their relationships. _manual_ is an
|
|
33
|
+
# optional reference to the UserManual object that uses this
|
|
34
|
+
# SyntaxReference.
|
|
31
35
|
def initialize(manual = nil)
|
|
32
36
|
@manual = manual
|
|
33
37
|
@messageHandler = MessageHandler.new(true)
|
|
@@ -69,7 +73,7 @@ class TaskJuggler
|
|
|
69
73
|
end
|
|
70
74
|
end
|
|
71
75
|
|
|
72
|
-
# Return a sorted Array with all keywords.
|
|
76
|
+
# Return a sorted Array with all keywords (as String objects).
|
|
73
77
|
def all
|
|
74
78
|
sorted = @keywords.keys.sort
|
|
75
79
|
# Register the neighbours with each keyword so we can use this info in
|
data/lib/TOCEntry.rb
CHANGED
data/lib/TableOfContents.rb
CHANGED
data/lib/Task.rb
CHANGED
|
@@ -32,25 +32,37 @@ class TaskJuggler
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def query_journal(query)
|
|
35
|
-
journalText(query, true)
|
|
35
|
+
journalText(query, true, false)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def query_journal_sub(query)
|
|
39
|
+
journalText(query, true, true)
|
|
36
40
|
end
|
|
37
41
|
|
|
38
42
|
private
|
|
39
43
|
|
|
40
44
|
# Create a blog-style list of all alert messages that match the Query.
|
|
41
|
-
def journalText(query, longVersion)
|
|
45
|
+
def journalText(query, longVersion, recursive)
|
|
42
46
|
# The components of the message are either UTF-8 text or RichText. For
|
|
43
47
|
# the RichText components, we use the originally provided markup since
|
|
44
48
|
# we compose the result as RichText markup first.
|
|
45
49
|
rText = ''
|
|
46
|
-
|
|
50
|
+
if recursive
|
|
51
|
+
list = @project['journal'].entriesByTaskR(self, query.start, query.end)
|
|
52
|
+
else
|
|
53
|
+
list = @project['journal'].entriesByTask(self, query.start, query.end)
|
|
54
|
+
end
|
|
47
55
|
list.reverse.each do |entry|
|
|
48
56
|
tsRecord = entry.timeSheetRecord
|
|
49
57
|
|
|
50
58
|
if entry.property.is_a?(Task)
|
|
51
59
|
levelRecord = @project['alertLevels'][entry.alertLevel]
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
if query.selfContained
|
|
61
|
+
alertName = "<nowiki>[#{levelRecord[1]}]</nowiki>"
|
|
62
|
+
else
|
|
63
|
+
alertName = "[[File:icons/flag-#{levelRecord[0]}.png|" +
|
|
64
|
+
"alt=[#{levelRecord[1]}]|text-bottom]]"
|
|
65
|
+
end
|
|
54
66
|
rText += "== #{alertName} <nowiki>#{entry.headline}</nowiki> ==\n" +
|
|
55
67
|
"''Reported on #{entry.date.to_s(query.timeFormat)}'' "
|
|
56
68
|
if entry.author
|
|
@@ -84,15 +96,14 @@ class TaskJuggler
|
|
|
84
96
|
|
|
85
97
|
# Now convert the RichText markup String into RichTextIntermediate
|
|
86
98
|
# format.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
"Line #{msg.lineNo}: #{msg.text}\n" +
|
|
93
|
-
"#{msg.line}"
|
|
99
|
+
unless (rti = RichText.new(rText, RTFHandlers.create(@project),
|
|
100
|
+
@project.messageHandler).
|
|
101
|
+
generateIntermediateFormat)
|
|
102
|
+
@project.messageHandler.warning(
|
|
103
|
+
'task_journal_text', 'Syntax error in journal text')
|
|
94
104
|
return nil
|
|
95
105
|
end
|
|
106
|
+
|
|
96
107
|
# No section numbers, please!
|
|
97
108
|
rti.sectionNumbers = false
|
|
98
109
|
# We use a special class to allow CSS formating.
|
data/lib/TaskJuggler.rb
CHANGED
|
@@ -45,17 +45,29 @@ class TaskJuggler
|
|
|
45
45
|
files.each do |file|
|
|
46
46
|
begin
|
|
47
47
|
@parser.open(file, master)
|
|
48
|
-
rescue TjException
|
|
48
|
+
rescue TjException => msg
|
|
49
|
+
if msg.message && !msg.message.empty?
|
|
50
|
+
@messageHandler.critical('parse', msg.message)
|
|
51
|
+
end
|
|
49
52
|
Log.exit('parser')
|
|
50
53
|
return false
|
|
51
54
|
end
|
|
52
55
|
if master
|
|
53
|
-
|
|
56
|
+
# The first file is considered the master file.
|
|
57
|
+
if (@project = @parser.parse('project')) == false
|
|
58
|
+
Log.exit('parser')
|
|
59
|
+
return false
|
|
60
|
+
end
|
|
54
61
|
master = false
|
|
55
62
|
else
|
|
63
|
+
# All other files.
|
|
56
64
|
@parser.setGlobalMacros
|
|
57
|
-
@parser.parse('properties')
|
|
65
|
+
if @parser.parse('properties') == false
|
|
66
|
+
Log.exit('parser')
|
|
67
|
+
return false
|
|
68
|
+
end
|
|
58
69
|
end
|
|
70
|
+
@project.inputFiles << file
|
|
59
71
|
@parser.close
|
|
60
72
|
end
|
|
61
73
|
|
|
@@ -70,9 +82,19 @@ class TaskJuggler
|
|
|
70
82
|
# Parse a file and add the content to the existing project. _fileName_ is
|
|
71
83
|
# the name of the file. _rule_ is the TextParser::Rule to start with.
|
|
72
84
|
def parseFile(fileName, rule)
|
|
73
|
-
|
|
85
|
+
begin
|
|
86
|
+
@parser.open(fileName, false)
|
|
87
|
+
@project.inputFiles << fileName
|
|
88
|
+
rescue TjException => msg
|
|
89
|
+
if msg.message && !msg.message.empty?
|
|
90
|
+
@messageHandler.critical('parse_file', msg.message)
|
|
91
|
+
end
|
|
92
|
+
return nil
|
|
93
|
+
end
|
|
94
|
+
|
|
74
95
|
@parser.setGlobalMacros
|
|
75
|
-
return nil if (res = @parser.parse(rule))
|
|
96
|
+
return nil if (res = @parser.parse(rule)) == false
|
|
97
|
+
|
|
76
98
|
@parser.close
|
|
77
99
|
res
|
|
78
100
|
end
|
|
@@ -83,7 +105,16 @@ class TaskJuggler
|
|
|
83
105
|
Log.enter('scheduler', 'Scheduling project ...')
|
|
84
106
|
#puts @project.to_s
|
|
85
107
|
@project.warnTsDeltas = @warnTsDeltas
|
|
86
|
-
|
|
108
|
+
|
|
109
|
+
begin
|
|
110
|
+
res = @project.schedule
|
|
111
|
+
rescue TjException => msg
|
|
112
|
+
if msg.message && !msg.message.empty?
|
|
113
|
+
@messageHandler.critical('scheduling_error', msg.message)
|
|
114
|
+
end
|
|
115
|
+
return false
|
|
116
|
+
end
|
|
117
|
+
|
|
87
118
|
Log.exit('scheduler')
|
|
88
119
|
res
|
|
89
120
|
end
|
|
@@ -95,9 +126,18 @@ class TaskJuggler
|
|
|
95
126
|
outputDir += '/' unless outputDir.empty? || outputDir[-1] == '/'
|
|
96
127
|
@project.outputDir = outputDir
|
|
97
128
|
Log.enter('reports', 'Generating reports ...')
|
|
98
|
-
|
|
129
|
+
|
|
130
|
+
begin
|
|
131
|
+
@project.generateReports(@maxCpuCores)
|
|
132
|
+
rescue TjException => msg
|
|
133
|
+
if msg.message && !msg.message.empty?
|
|
134
|
+
@messageHandler.critical('generate_reports', msg.message)
|
|
135
|
+
end
|
|
136
|
+
return false
|
|
137
|
+
end
|
|
138
|
+
|
|
99
139
|
Log.exit('reports')
|
|
100
|
-
|
|
140
|
+
true
|
|
101
141
|
end
|
|
102
142
|
|
|
103
143
|
# Generate the report with the ID _reportId_. If _regExpMode_ is true,
|
|
@@ -109,7 +149,10 @@ class TaskJuggler
|
|
|
109
149
|
begin
|
|
110
150
|
Log.enter('generateReport', 'Generating report #{reportId} ...')
|
|
111
151
|
@project.generateReport(reportId, regExpMode, dynamicAttributes)
|
|
112
|
-
rescue TjException
|
|
152
|
+
rescue TjException => msg
|
|
153
|
+
if msg.message && !msg.message.empty?
|
|
154
|
+
@messageHandler.critical('generate_report', msg.message)
|
|
155
|
+
end
|
|
113
156
|
Log.exit('generateReport')
|
|
114
157
|
return false
|
|
115
158
|
end
|
|
@@ -117,14 +160,16 @@ class TaskJuggler
|
|
|
117
160
|
true
|
|
118
161
|
end
|
|
119
162
|
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
# matching IDs are listed.
|
|
163
|
+
# List the details of the report with _reportId_ or if _regExpMode_ the
|
|
164
|
+
# reports that match the regular expression in _reportId_.
|
|
123
165
|
def listReports(reportId, regExpMode)
|
|
124
166
|
begin
|
|
125
167
|
Log.enter('listReports', 'Generating report list for #{reportId} ...')
|
|
126
168
|
@project.listReports(reportId, regExpMode)
|
|
127
|
-
rescue TjException
|
|
169
|
+
rescue TjException => msg
|
|
170
|
+
if msg.message && !msg.message.empty?
|
|
171
|
+
@messageHandler.critical('list_reports', msg.message)
|
|
172
|
+
end
|
|
128
173
|
Log.exit('listReports')
|
|
129
174
|
return false
|
|
130
175
|
end
|
|
@@ -149,17 +194,14 @@ class TaskJuggler
|
|
|
149
194
|
'scenarioIdx' => @project['trackingScenarioIdx'],
|
|
150
195
|
'start' => ts.interval.start,
|
|
151
196
|
'end' => ts.interval.end,
|
|
152
|
-
'timeFormat' => '%Y-%m-%d'
|
|
197
|
+
'timeFormat' => '%Y-%m-%d',
|
|
198
|
+
'selfContained' => true }
|
|
153
199
|
query = Query.new(queryAttrs)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
rti.parIndent = 2
|
|
160
|
-
rti.preIndent = 4
|
|
161
|
-
puts rti.to_s
|
|
162
|
-
rescue TjException
|
|
200
|
+
puts ts.resource.query_journal(query).richText.inputText
|
|
201
|
+
rescue TjException => msg
|
|
202
|
+
if msg.message && !msg.message.empty?
|
|
203
|
+
@messageHandler.critical('check_time_sheet', msg.message)
|
|
204
|
+
end
|
|
163
205
|
Log.exit('checkTimeSheet')
|
|
164
206
|
return false
|
|
165
207
|
end
|
|
@@ -181,17 +223,14 @@ class TaskJuggler
|
|
|
181
223
|
'timeFormat' => '%Y-%m-%d',
|
|
182
224
|
'start' => ss[1],
|
|
183
225
|
'end' => ss[2],
|
|
184
|
-
'timeFormat' => '%Y-%m-%d'
|
|
226
|
+
'timeFormat' => '%Y-%m-%d',
|
|
227
|
+
'selfContained' => true }
|
|
185
228
|
query = Query.new(queryAttrs)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
rti.parIndent = 2
|
|
192
|
-
rti.preIndent = 4
|
|
193
|
-
puts rti.to_s
|
|
194
|
-
rescue TjException
|
|
229
|
+
puts ss[0].query_dashboard(query).richText.inputText
|
|
230
|
+
rescue TjException => msg
|
|
231
|
+
if msg.message && !msg.message.empty?
|
|
232
|
+
@messageHandler.critical('check_status_sheet', msg.message)
|
|
233
|
+
end
|
|
195
234
|
Log.exit('checkStatusSheet')
|
|
196
235
|
return false
|
|
197
236
|
end
|
data/lib/TaskScenario.rb
CHANGED
|
@@ -324,7 +324,10 @@ class TaskJuggler
|
|
|
324
324
|
# be called to do some more housekeeping. It computes some derived data
|
|
325
325
|
# based on the just scheduled values.
|
|
326
326
|
def finishScheduling
|
|
327
|
-
|
|
327
|
+
# The completion degree calculation is done recursively. So we only call
|
|
328
|
+
# it for top-level tasks.
|
|
329
|
+
calcCompletion unless @property.parent
|
|
330
|
+
|
|
328
331
|
# This list is no longer needed, so let's save some memory. Set it to
|
|
329
332
|
# nil so we can detect accidental use.
|
|
330
333
|
@candidates = nil
|
|
@@ -434,12 +437,33 @@ class TaskJuggler
|
|
|
434
437
|
task = dependency.task
|
|
435
438
|
limit = task[dependency.onEnd ? 'end' : 'start', @scenarioIdx]
|
|
436
439
|
next if limit.nil?
|
|
437
|
-
if
|
|
440
|
+
if a('start') < limit
|
|
438
441
|
error('task_pred_before',
|
|
439
442
|
"Task #{@property.fullId} must start after " +
|
|
440
443
|
"#{dependency.onEnd ? 'end' : 'start'} of task " +
|
|
441
444
|
"#{task.fullId}.")
|
|
442
445
|
end
|
|
446
|
+
if dependency.gapDuration > 0
|
|
447
|
+
if limit + dependency.gapDuration > a('start')
|
|
448
|
+
error('task_pred_before_gd',
|
|
449
|
+
"Task #{@property.fullId} must start " +
|
|
450
|
+
"#{dependency.gapDuration / (60 * 60 * 24)} days after " +
|
|
451
|
+
"#{dependency.onEnd ? 'end' : 'start'} of task " +
|
|
452
|
+
"#{task.fullId}. TaskJuggler cannot enforce this condition " +
|
|
453
|
+
"because the task is scheduled ALAP (finish-to-start).")
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
if dependency.gapLength > 0
|
|
457
|
+
if calcLength(limit, a('start')) < dependency.gapLength
|
|
458
|
+
error('task_pred_before_gl',
|
|
459
|
+
"Task #{@property.fullId} must start " +
|
|
460
|
+
"#{@project.slotsToDays(dependency.gapLength)} " +
|
|
461
|
+
"working days after " +
|
|
462
|
+
"#{dependency.onEnd ? 'end' : 'start'} of task " +
|
|
463
|
+
"#{task.fullId}. TaskJuggler cannot enforce this condition " +
|
|
464
|
+
"because the task is scheduled ALAP (finish-to-start).")
|
|
465
|
+
end
|
|
466
|
+
end
|
|
443
467
|
end
|
|
444
468
|
|
|
445
469
|
# Check that all following tasks end before this task
|
|
@@ -452,6 +476,27 @@ class TaskJuggler
|
|
|
452
476
|
"Task #{@property.fullId} must end before " +
|
|
453
477
|
"#{dependency.onEnd ? 'end' : 'start'} of task #{task.fullId}.")
|
|
454
478
|
end
|
|
479
|
+
if dependency.gapDuration > 0
|
|
480
|
+
if limit - dependency.gapDuration < a('end')
|
|
481
|
+
error('task_succ_after_gd',
|
|
482
|
+
"Task #{@property.fullId} must end " +
|
|
483
|
+
"#{dependency.gapDuration / (60 * 60 * 24)} days before " +
|
|
484
|
+
"#{dependency.onEnd ? 'end' : 'start'} of task " +
|
|
485
|
+
"#{task.fullId}. TaskJuggler cannot enforce this condition " +
|
|
486
|
+
"because the task is scheduled ASAP (start-to-finish).")
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
if dependency.gapLength > 0
|
|
490
|
+
if calcLength(a('end'), limit) < dependency.gapLength
|
|
491
|
+
error('task_succ_after_gl',
|
|
492
|
+
"Task #{@property.fullId} must end " +
|
|
493
|
+
"#{@project.slotsToDays(dependency.gapLength)} " +
|
|
494
|
+
"working days before " +
|
|
495
|
+
"#{dependency.onEnd ? 'end' : 'start'} of task " +
|
|
496
|
+
"#{task.fullId}. TaskJuggler cannot enforce this condition " +
|
|
497
|
+
"because the task is scheduled ASAP (start-to-finish).")
|
|
498
|
+
end
|
|
499
|
+
end
|
|
455
500
|
end
|
|
456
501
|
|
|
457
502
|
if a('milestone') && a('start') != a('end')
|
|
@@ -497,8 +542,9 @@ class TaskJuggler
|
|
|
497
542
|
def checkForLoops(path, atEnd, fromOutside)
|
|
498
543
|
# Check if we have been here before on this path.
|
|
499
544
|
if path.include?([ @property, atEnd ])
|
|
500
|
-
|
|
501
|
-
|
|
545
|
+
warning('loop_detected',
|
|
546
|
+
"Loop detected at #{atEnd ? 'end' : 'start'} " +
|
|
547
|
+
"of task #{@property.fullId}", false)
|
|
502
548
|
skip = true
|
|
503
549
|
path.each do |t, e|
|
|
504
550
|
if t == @property && e == atEnd
|
|
@@ -507,7 +553,8 @@ class TaskJuggler
|
|
|
507
553
|
end
|
|
508
554
|
next if skip
|
|
509
555
|
info("loop_at_#{e ? 'end' : 'start'}",
|
|
510
|
-
"Loop ctnd. at #{e ? 'end' : 'start'} of task #{t.fullId}",
|
|
556
|
+
"Loop ctnd. at #{e ? 'end' : 'start'} of task #{t.fullId}",
|
|
557
|
+
t.sourceFileInfo)
|
|
511
558
|
end
|
|
512
559
|
error('loop_end', "Aborting")
|
|
513
560
|
end
|
|
@@ -1098,12 +1145,8 @@ class TaskJuggler
|
|
|
1098
1145
|
end
|
|
1099
1146
|
|
|
1100
1147
|
def query_complete(query)
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
query.string = "#{complete}%"
|
|
1104
|
-
else
|
|
1105
|
-
query.string = ''
|
|
1106
|
-
end
|
|
1148
|
+
query.sortable = query.numerical = complete = a('complete').to_i
|
|
1149
|
+
query.string = "#{complete}%"
|
|
1107
1150
|
end
|
|
1108
1151
|
|
|
1109
1152
|
# Compute the cost generated by this Task for a given Account during a given
|
|
@@ -1172,10 +1215,10 @@ class TaskJuggler
|
|
|
1172
1215
|
str += "* <nowiki>#{task.name}</nowiki> (#{task.fullId}) "
|
|
1173
1216
|
if onEnd
|
|
1174
1217
|
taskEnd = task['end', query.scenarioIdx].to_s(query.timeFormat)
|
|
1175
|
-
str += "[->] #{taskEnd}"
|
|
1218
|
+
str += "<nowiki>[->]</nowiki> #{taskEnd}"
|
|
1176
1219
|
else
|
|
1177
1220
|
taskStart = task['start', query.scenarioIdx].to_s(query.timeFormat)
|
|
1178
|
-
str += "[->[ #{taskStart}"
|
|
1221
|
+
str += "<nowiki>[->[</nowiki> #{taskStart}"
|
|
1179
1222
|
end
|
|
1180
1223
|
str += "\n"
|
|
1181
1224
|
end
|
|
@@ -1184,16 +1227,19 @@ class TaskJuggler
|
|
|
1184
1227
|
str += "* <nowiki>#{task.name}</nowiki> (#{task.fullId}) "
|
|
1185
1228
|
if onEnd
|
|
1186
1229
|
taskEnd = task['end', query.scenarioIdx].to_s(query.timeFormat)
|
|
1187
|
-
str += "]->] #{taskEnd}"
|
|
1230
|
+
str += "<nowiki>]->]</nowiki> #{taskEnd}"
|
|
1188
1231
|
else
|
|
1189
1232
|
taskStart = task['start', query.scenarioIdx].to_s(query.timeFormat)
|
|
1190
|
-
str += "]->[ #{taskStart}"
|
|
1233
|
+
str += "<nowiki>]->[</nowiki> #{taskStart}"
|
|
1191
1234
|
end
|
|
1192
1235
|
str += "\n"
|
|
1193
1236
|
end
|
|
1194
1237
|
|
|
1195
|
-
rText = RichText.new(str)
|
|
1196
|
-
query.rti = rText.generateIntermediateFormat
|
|
1238
|
+
rText = RichText.new(str, [], @property.project.messageHandler)
|
|
1239
|
+
unless (query.rti = rText.generateIntermediateFormat)
|
|
1240
|
+
@property.project.messageHandler.warning(
|
|
1241
|
+
'task_sc_followers', 'Syntax error in followers')
|
|
1242
|
+
end
|
|
1197
1243
|
end
|
|
1198
1244
|
|
|
1199
1245
|
def query_precursors(query)
|
|
@@ -1204,10 +1250,10 @@ class TaskJuggler
|
|
|
1204
1250
|
str += "* <nowiki>#{task.name}</nowiki> (#{task.fullId}) "
|
|
1205
1251
|
if onEnd
|
|
1206
1252
|
taskEnd = task['end', query.scenarioIdx].to_s(query.timeFormat)
|
|
1207
|
-
str += "]->] #{taskEnd}"
|
|
1253
|
+
str += "<nowiki>]->]</nowiki> #{taskEnd}"
|
|
1208
1254
|
else
|
|
1209
1255
|
taskStart = task['start', query.scenarioIdx].to_s(query.timeFormat)
|
|
1210
|
-
str += "[->[ #{taskStart}"
|
|
1256
|
+
str += "<nowiki>[->[</nowiki> #{taskStart}"
|
|
1211
1257
|
end
|
|
1212
1258
|
str += "\n"
|
|
1213
1259
|
end
|
|
@@ -1216,10 +1262,10 @@ class TaskJuggler
|
|
|
1216
1262
|
str += "* <nowiki>#{task.name}</nowiki> (#{task.fullId}) "
|
|
1217
1263
|
if onEnd
|
|
1218
1264
|
taskEnd = task['end', query.scenarioIdx].to_s(query.timeFormat)
|
|
1219
|
-
str += "[->] #{taskEnd}"
|
|
1265
|
+
str += "<nowiki>[->]</nowiki> #{taskEnd}"
|
|
1220
1266
|
else
|
|
1221
1267
|
taskStart = task['start', query.scenarioIdx].to_s(query.timeFormat)
|
|
1222
|
-
str += "]->[ #{taskStart}"
|
|
1268
|
+
str += "<nowiki>]->[</nowiki> #{taskStart}"
|
|
1223
1269
|
end
|
|
1224
1270
|
str += "\n"
|
|
1225
1271
|
end
|
|
@@ -1259,7 +1305,7 @@ class TaskJuggler
|
|
|
1259
1305
|
|
|
1260
1306
|
def query_targets(query)
|
|
1261
1307
|
targetList = PropertyList.new(@project.tasks, false)
|
|
1262
|
-
targets(targetList)
|
|
1308
|
+
targets(targetList, true)
|
|
1263
1309
|
targetList.delete(@property)
|
|
1264
1310
|
targetList.setSorting([['start', true, @scenarioIdx],
|
|
1265
1311
|
['seqno', true, -1 ]])
|
|
@@ -1569,7 +1615,6 @@ class TaskJuggler
|
|
|
1569
1615
|
return unless found
|
|
1570
1616
|
end
|
|
1571
1617
|
|
|
1572
|
-
iv = Interval.new(date, date + slotDuration)
|
|
1573
1618
|
a('allocate').each do |allocation|
|
|
1574
1619
|
next unless allocation.onShift?(date)
|
|
1575
1620
|
|
|
@@ -1640,6 +1685,16 @@ class TaskJuggler
|
|
|
1640
1685
|
true
|
|
1641
1686
|
end
|
|
1642
1687
|
|
|
1688
|
+
# Calculate the number of general working time slots between the TjTime
|
|
1689
|
+
# objects _d1_ and _d2_.
|
|
1690
|
+
def calcLength(d1, d2)
|
|
1691
|
+
slots = 0
|
|
1692
|
+
while d1 < d2
|
|
1693
|
+
slots += 1 if @project.isWorkingTime(d1)
|
|
1694
|
+
d1 += @project['scheduleGranularity']
|
|
1695
|
+
end
|
|
1696
|
+
slots
|
|
1697
|
+
end
|
|
1643
1698
|
|
|
1644
1699
|
# Register the user provided bookings with the Resource scoreboards. A
|
|
1645
1700
|
# booking describes the assignment of a Resource to a certain Task for a
|
|
@@ -1649,7 +1704,7 @@ class TaskJuggler
|
|
|
1649
1704
|
a('booking').each do |booking|
|
|
1650
1705
|
unless booking.resource.leaf?
|
|
1651
1706
|
error('booking_resource_not_leaf',
|
|
1652
|
-
"Booked resources may not be group resources",
|
|
1707
|
+
"Booked resources may not be group resources",
|
|
1653
1708
|
booking.sourceFileInfo)
|
|
1654
1709
|
end
|
|
1655
1710
|
unless a('forward') || scheduled
|
|
@@ -1866,51 +1921,59 @@ class TaskJuggler
|
|
|
1866
1921
|
# If the user provided a completion degree we are not touching it.
|
|
1867
1922
|
if @property.provided('complete', @scenarioIdx)
|
|
1868
1923
|
calcStatus
|
|
1869
|
-
return
|
|
1924
|
+
return a('complete')
|
|
1870
1925
|
end
|
|
1871
1926
|
|
|
1927
|
+
# We cannot compute a completion degree without a start or end date.
|
|
1872
1928
|
if a('start').nil? || a('end').nil?
|
|
1873
1929
|
@property['complete', @scenarioIdx] = 0.0
|
|
1874
1930
|
@property['status', @scenarioIdx] = 'unknown'
|
|
1875
|
-
return
|
|
1931
|
+
return nil
|
|
1876
1932
|
end
|
|
1877
1933
|
|
|
1934
|
+
completion = 0.0
|
|
1878
1935
|
if a('milestone')
|
|
1879
|
-
|
|
1936
|
+
# Milestones are either 0% or 100% complete.
|
|
1937
|
+
@property['complete', @scenarioIdx] = completion =
|
|
1880
1938
|
@property['end', @scenarioIdx] <= @project['now'] ? 100.0 : 0.0
|
|
1881
1939
|
@property['status', @scenarioIdx] =
|
|
1882
1940
|
a('end') <= @project['now'] ? 'done' : 'not reached'
|
|
1883
1941
|
else
|
|
1884
|
-
|
|
1885
|
-
|
|
1942
|
+
# The task is in progress. Calculate the current completion
|
|
1943
|
+
# degree.
|
|
1944
|
+
if !property.leaf?
|
|
1945
|
+
# For container task the completion degree is the average of the
|
|
1946
|
+
# sub tasks.
|
|
1947
|
+
completion = 0.0
|
|
1948
|
+
@property.children.each do |child|
|
|
1949
|
+
return nil unless (comp = child.calcCompletion(@scenarioIdx))
|
|
1950
|
+
completion += comp
|
|
1951
|
+
end
|
|
1952
|
+
completion /= @property.children.length
|
|
1953
|
+
elsif a('end') <= @project['now']
|
|
1886
1954
|
# The task has ended already. It's 100% complete.
|
|
1887
1955
|
completion = 100.0
|
|
1888
1956
|
elsif @project['now'] <= a('start')
|
|
1889
1957
|
# The task has not started yet. Its' 0% complete.
|
|
1890
1958
|
completion = 0.0
|
|
1959
|
+
elsif a('effort') > 0
|
|
1960
|
+
# Effort based leaf tasks. The completion degree is the percentage
|
|
1961
|
+
# of effort that has been done already.
|
|
1962
|
+
done = getEffectiveWork(@project.dateToIdx(a('start')),
|
|
1963
|
+
@project.dateToIdx(@project['now']))
|
|
1964
|
+
total = @project.convertToDailyLoad(
|
|
1965
|
+
a('effort') * @project['scheduleGranularity'])
|
|
1966
|
+
completion = done / total * 100.0
|
|
1891
1967
|
else
|
|
1892
|
-
#
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
# Effort based leaf tasks. The completion degree is the percantage
|
|
1896
|
-
# of effort that has been done already.
|
|
1897
|
-
done = getEffectiveWork(@project.dateToIdx(a('start')),
|
|
1898
|
-
@project.dateToIdx(@project['now']))
|
|
1899
|
-
total = @project.convertToDailyLoad(
|
|
1900
|
-
a('effort') * @project['scheduleGranularity'])
|
|
1901
|
-
completion = done / total * 100.0
|
|
1902
|
-
else
|
|
1903
|
-
# Container tasks and length/duration leaf tasks. There is no way
|
|
1904
|
-
# we can compute the completion degree of a container task with a
|
|
1905
|
-
# mix of effort and duration task in a meaningful way. So, we
|
|
1906
|
-
# just go by duration.
|
|
1907
|
-
completion = ((@project['now'] - a('start')) /
|
|
1908
|
-
(a('end') - a('start'))) * 100.0
|
|
1909
|
-
end
|
|
1968
|
+
# Length/duration leaf tasks.
|
|
1969
|
+
completion = ((@project['now'] - a('start')) /
|
|
1970
|
+
(a('end') - a('start'))) * 100.0
|
|
1910
1971
|
end
|
|
1911
1972
|
@property['complete', @scenarioIdx] = completion
|
|
1912
1973
|
calcStatus
|
|
1913
1974
|
end
|
|
1975
|
+
|
|
1976
|
+
completion
|
|
1914
1977
|
end
|
|
1915
1978
|
|
|
1916
1979
|
# Calculate the status of the task based on the 'complete' attribute.
|
|
@@ -1927,20 +1990,35 @@ class TaskJuggler
|
|
|
1927
1990
|
|
|
1928
1991
|
# Recursively compile a list of Task properties which depend on the
|
|
1929
1992
|
# current task.
|
|
1930
|
-
def targets(list)
|
|
1993
|
+
def targets(list, includeChildren)
|
|
1994
|
+
# Ignore tasks that we have already included in the list.
|
|
1995
|
+
return if list.include?(@property)
|
|
1996
|
+
|
|
1931
1997
|
# A target must be a leaf function that has no direct or indirect
|
|
1932
|
-
# (through parent) following tasks.
|
|
1933
|
-
|
|
1998
|
+
# (through parent) following tasks. Only milestones are recognized as
|
|
1999
|
+
# targets.
|
|
2000
|
+
if @property.leaf? && !hasSuccessors && a('milestone')
|
|
1934
2001
|
list << @property
|
|
1935
2002
|
return
|
|
1936
2003
|
end
|
|
1937
2004
|
|
|
1938
2005
|
a('endsuccs').each do |t, onEnd|
|
|
1939
|
-
t.targets(@scenarioIdx, list)
|
|
2006
|
+
t.targets(@scenarioIdx, list, false)
|
|
2007
|
+
end
|
|
2008
|
+
|
|
2009
|
+
# Check for indirect followers.
|
|
2010
|
+
if @property.parent
|
|
2011
|
+
@property.parent.targets(@scenarioIdx, list, false)
|
|
1940
2012
|
end
|
|
1941
2013
|
|
|
1942
|
-
#
|
|
1943
|
-
|
|
2014
|
+
# Also include targets of child tasks. The recursive iteration of child
|
|
2015
|
+
# tasks is limited to the tested task only. The followers are not
|
|
2016
|
+
# iterated.
|
|
2017
|
+
if includeChildren
|
|
2018
|
+
@property.children.each do |child|
|
|
2019
|
+
child.targets(@scenarioIdx, list, true)
|
|
2020
|
+
end
|
|
2021
|
+
end
|
|
1944
2022
|
end
|
|
1945
2023
|
|
|
1946
2024
|
# Compute the turnover generated by this Task for a given Account _account_
|