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 @@ - +

+