diff --git a/expert/browser/report.py b/expert/browser/report.py
index b8f5f9b..27912eb 100644
--- a/expert/browser/report.py
+++ b/expert/browser/report.py
@@ -85,7 +85,7 @@ class ResultsView(NodeView):
def reportInstance(self):
instance = component.getAdapter(self.report, IReportInstance,
name=self.report.reportType)
- instance.request = self.request
+ instance.view = self
return instance
#@Lazy
diff --git a/expert/configure.zcml b/expert/configure.zcml
index 03543ad..68c5d79 100644
--- a/expert/configure.zcml
+++ b/expert/configure.zcml
@@ -22,9 +22,9 @@
provides="loops.expert.report.IReport" trusted="True" />
+ interface="loops.expert.report.IReport" />
+ set_schema="loops.expert.report.IReport" />
>> from loops.expert.report import IReport, Report
+ >>> component.provideAdapter(Report)
+ >>> tReport = addAndConfigureObject(concepts, Concept, 'report',
+ ... title=u'Report', conceptType=concepts.getTypeConcept(),
+ ... typeInterface=IReport)
+ >>> hasReport = addAndConfigureObject(concepts, Concept, 'hasreport',
+ ... title=u'has Report', conceptType=concepts.getPredicateType())
+
+Now we can create a report and register it as the report for the task
+used above.
+
+ >>> workStatement = addAndConfigureObject(concepts, Concept, 'work_statement',
+ ... title=u'Work Statement', conceptType=tReport,
+ ... reportType='work_report')
+ >>> workStatement.assignChild(task01, hasReport)
+
+The executable report is a report instance that is an adapter to the
+(adapted) report instance.
+
>>> from loops.organize.work.report import WorkReportInstance
>>> from loops.expert.report import IReportInstance
>>> component.provideAdapter(WorkReportInstance,
... provides=IReportInstance,
... name='work_report')
+The user interface to the report is a report view, the results are presented
+in a results view.
+
+ >>> from loops.view import Node
+ >>> reportNode = addAndConfigureObject(home, Node, 'report',
+ ... title=u'Report', target=workStatement)
+ >>> from loops.expert.browser.report import ReportView, ResultsView
+ >>> resultsView = ResultsView(reportNode, TestRequest())
+
+ >>> results = resultsView.results()
+ >>> len(results.data)
+ 2
+
Fin de partie
=============
diff --git a/organize/work/report.py b/organize/work/report.py
index 71ec849..d7bab83 100644
--- a/organize/work/report.py
+++ b/organize/work/report.py
@@ -28,14 +28,17 @@ from cybertools.composer.report.base import Report
from cybertools.composer.report.base import LeafQueryCriteria, CompoundQueryCriteria
from cybertools.composer.report.field import Field
from cybertools.composer.report.result import ResultSet, Row as BaseRow
+from cybertools.organize.interfaces import IWorkItems
from cybertools.util.jeep import Jeep
+from loops.common import adapted, baseObject
from loops.expert.report import ReportInstance
+from loops import util
results_template = ViewPageTemplateFile('results.pt')
-task = Field('task', u'Task',
- description=u'The task to which work items belong.',
+tasks = Field('tasks', u'Tasks',
+ description=u'The tasks to which work items belong.',
executionSteps=['query', 'output', 'sort'])
work = Field('work', u'Work',
description=u'The short description of the work.',
@@ -65,12 +68,20 @@ class WorkReportInstance(ReportInstance):
label = u'Work Report'
rowFactory = WorkRow
- fields = Jeep((day, dayFrom, dayTo, task, work, workDescription))
+ fields = Jeep((day, dayFrom, dayTo, tasks, work, workDescription))
defaultOutputFields = fields
- @Lazy
+ @property
def queryCriteria(self):
- # TODO: take from persistent report where appropriate
+ crit = self.context.queryCriteria
+ if crit is None:
+ f = self.fields['tasks']
+ tasks = baseObject(self.context).getChildren([self.hasReportPredicate])
+ crit = [LeafQueryCriteria(f.name, f.operator, tasks, f)]
+ return CompoundQueryCriteria(crit)
+
+ @property
+ def xx_queryCriteria(self):
crit = [LeafQueryCriteria(f.name, f.operator, None, f)
for f in self.getAllQueryFields()]
return CompoundQueryCriteria(crit)
@@ -79,8 +90,31 @@ class WorkReportInstance(ReportInstance):
return results_template.macros[name]
def selectObjects(self, parts):
- task = parts.get('task')
- if not task:
- return []
- return []
+ result = []
+ tasks = parts.pop('tasks').comparisonValue
+ for t in list(tasks):
+ tasks.extend(self.getAllSubtasks(t))
+ for t in tasks:
+ result.extend(self.selectWorkItems(t, parts))
+ # TODO: remove parts already used for selection from parts list
+ return result
+ def selectWorkItems(self, task, parts):
+ wi = self.workItems
+ return wi.query(task=util.getUidForObject(task))
+
+ def getAllSubtasks(self, concept):
+ result = []
+ for c in concept.getChildren():
+ if c.conceptType == self.taskType:
+ result.append(c)
+ result.extend(self.getAllSubtasks(c))
+ return result
+
+ @Lazy
+ def taskType(self):
+ return self.conceptManager['task']
+
+ @Lazy
+ def workItems(self):
+ return IWorkItems(self.recordManager['work'])
diff --git a/organize/work/results.pt b/organize/work/results.pt
index 0d1cec0..fbd482b 100644
--- a/organize/work/results.pt
+++ b/organize/work/results.pt
@@ -11,7 +11,8 @@
-
+
+