work in progress: extend reporting features - report 'meeting minutes'
This commit is contained in:
parent
0162adea94
commit
9f9e350933
3 changed files with 109 additions and 18 deletions
|
@ -2,8 +2,6 @@
|
||||||
loops - Linked Objects for Organization and Processing Services
|
loops - Linked Objects for Organization and Processing Services
|
||||||
===============================================================
|
===============================================================
|
||||||
|
|
||||||
($Id$)
|
|
||||||
|
|
||||||
Let's do some basic setup
|
Let's do some basic setup
|
||||||
|
|
||||||
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
|
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
|
||||||
|
@ -194,6 +192,9 @@ In addition we need a predicate that connects one or more tasks with a report.
|
||||||
>>> hasReport = addAndConfigureObject(concepts, Concept, 'hasreport',
|
>>> hasReport = addAndConfigureObject(concepts, Concept, 'hasreport',
|
||||||
... title=u'has Report', conceptType=concepts.getPredicateType())
|
... title=u'has Report', conceptType=concepts.getPredicateType())
|
||||||
|
|
||||||
|
Work statement report
|
||||||
|
---------------------
|
||||||
|
|
||||||
Now we can create a report and register it as the report for the task
|
Now we can create a report and register it as the report for the task
|
||||||
used above.
|
used above.
|
||||||
|
|
||||||
|
@ -235,6 +236,53 @@ in a results view.
|
||||||
{'effort': 900}
|
{'effort': 900}
|
||||||
|
|
||||||
|
|
||||||
|
Meeting Minutes
|
||||||
|
===============
|
||||||
|
|
||||||
|
We can use an event with assigned tasks as the basis for planning a meeting
|
||||||
|
and recording information about the tasks.
|
||||||
|
|
||||||
|
Let's start with creating an a event and assigning it a task.
|
||||||
|
|
||||||
|
>>> from loops.organize.interfaces import ITask
|
||||||
|
>>> tEvent = addAndConfigureObject(concepts, Concept, 'event',
|
||||||
|
... title=u'Event', conceptType=concepts.getTypeConcept(),
|
||||||
|
... typeInterface=ITask)
|
||||||
|
|
||||||
|
>>> ev01 = addAndConfigureObject(concepts, Concept, 'ev01',
|
||||||
|
... title=u'loops Meeting', conceptType=tEvent)
|
||||||
|
>>> ev01.assignChild(task01)
|
||||||
|
|
||||||
|
Now we create the meeting minutes report. We assign the event type as a
|
||||||
|
child in order to provide the information for which types of objects the
|
||||||
|
report is available.
|
||||||
|
|
||||||
|
>>> from loops.organize.work.report import MeetingMinutes
|
||||||
|
>>> component.provideAdapter(MeetingMinutes, provides=IReportInstance,
|
||||||
|
... name='meeting_minutes')
|
||||||
|
|
||||||
|
>>> meetingMinutes = addAndConfigureObject(concepts, Concept, 'meeting_minutes',
|
||||||
|
... title=u'Meeting Minutes', conceptType=tReport,
|
||||||
|
... reportType='meeting_minutes')
|
||||||
|
>>> meetingMinutes.assignChild(tEvent, hasReport)
|
||||||
|
|
||||||
|
We can now access the report using a results view.
|
||||||
|
|
||||||
|
>>> from loops.util import getUidForObject
|
||||||
|
>>> input = dict(tasks=getUidForObject(ev01))
|
||||||
|
>>> resultsView = ResultsView(home, TestRequest(form=input))
|
||||||
|
>>> resultsView.virtualTargetObject = meetingMinutes
|
||||||
|
|
||||||
|
>>> results = resultsView.results()
|
||||||
|
>>> len(list(results))
|
||||||
|
1
|
||||||
|
>>> for row in results:
|
||||||
|
... for col in resultsView.displayedColumns:
|
||||||
|
... print col.getDisplayValue(row),
|
||||||
|
... print
|
||||||
|
loops Development
|
||||||
|
|
||||||
|
|
||||||
Fin de partie
|
Fin de partie
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,17 @@
|
||||||
set_schema="loops.expert.report.IReportInstance" />
|
set_schema="loops.expert.report.IReportInstance" />
|
||||||
</zope:class>
|
</zope:class>
|
||||||
|
|
||||||
|
<zope:adapter factory="loops.organize.work.report.MeetingMinutes"
|
||||||
|
name="meeting_minutes"
|
||||||
|
provides="loops.expert.report.IReportInstance"
|
||||||
|
trusted="True" />
|
||||||
|
<zope:class class="loops.organize.work.report.MeetingMinutes">
|
||||||
|
<require permission="zope.View"
|
||||||
|
interface="loops.expert.report.IReportInstance" />
|
||||||
|
<require permission="zope.ManageContent"
|
||||||
|
set_schema="loops.expert.report.IReportInstance" />
|
||||||
|
</zope:class>
|
||||||
|
|
||||||
<!-- setup -->
|
<!-- setup -->
|
||||||
|
|
||||||
<zope:adapter factory="loops.organize.work.setup.SetupManager"
|
<zope:adapter factory="loops.organize.work.setup.SetupManager"
|
||||||
|
|
|
@ -113,7 +113,7 @@ title = Field('title', u'Title',
|
||||||
executionSteps=['output'])
|
executionSteps=['output'])
|
||||||
description = Field('description', u'Description',
|
description = Field('description', u'Description',
|
||||||
description=u'The long description of the work.',
|
description=u'The long description of the work.',
|
||||||
executionSteps=['x_output'])
|
executionSteps=['output'])
|
||||||
duration = DurationField('duration', u'Duration',
|
duration = DurationField('duration', u'Duration',
|
||||||
description=u'The duration of the work.',
|
description=u'The duration of the work.',
|
||||||
executionSteps=['output'])
|
executionSteps=['output'])
|
||||||
|
@ -125,6 +125,8 @@ state = Field('state', u'State',
|
||||||
executionSteps=['query', 'output'])
|
executionSteps=['query', 'output'])
|
||||||
|
|
||||||
|
|
||||||
|
# basic definitions and work report instance
|
||||||
|
|
||||||
class WorkRow(BaseRow):
|
class WorkRow(BaseRow):
|
||||||
|
|
||||||
def getRawValue(self, attr):
|
def getRawValue(self, attr):
|
||||||
|
@ -161,11 +163,13 @@ class WorkReportInstance(ReportInstance):
|
||||||
rowFactory = WorkRow
|
rowFactory = WorkRow
|
||||||
|
|
||||||
fields = Jeep((dayFrom, dayTo, tasks,
|
fields = Jeep((dayFrom, dayTo, tasks,
|
||||||
day, timeStart, timeEnd, task, party, title, description,
|
day, timeStart, timeEnd, task, party, title, #description,
|
||||||
duration, effort, state))
|
duration, effort, state))
|
||||||
|
|
||||||
defaultOutputFields = fields
|
defaultOutputFields = fields
|
||||||
defaultSortCriteria = (day, timeStart,)
|
defaultSortCriteria = (day, timeStart,)
|
||||||
|
states = ('done', 'done_x', 'finished')
|
||||||
|
taskTypeNames = ('task', 'event', 'project')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def queryCriteria(self):
|
def queryCriteria(self):
|
||||||
|
@ -183,22 +187,20 @@ class WorkReportInstance(ReportInstance):
|
||||||
|
|
||||||
def selectObjects(self, parts):
|
def selectObjects(self, parts):
|
||||||
result = []
|
result = []
|
||||||
tasks = [util.getObjectForUid(t) for t in parts.pop('tasks').comparisonValue]
|
for t in self.getTasks(parts):
|
||||||
for t in list(tasks):
|
|
||||||
tasks.extend(self.getAllSubtasks(t))
|
|
||||||
for t in tasks:
|
|
||||||
result.extend(self.selectWorkItems(t, parts))
|
result.extend(self.selectWorkItems(t, parts))
|
||||||
# remove parts already used for selection from parts list:
|
# remove parts already used for selection from parts list:
|
||||||
parts.pop('userName', None)
|
parts.pop('userName', None)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def selectWorkItems(self, task, parts):
|
def getTasks(self, parts):
|
||||||
states = ['done', 'done_x', 'finished']
|
taskIds = parts.pop('tasks').comparisonValue
|
||||||
kw = dict(task=util.getUidForObject(task), state=states)
|
if not isinstance(taskIds, (list, tuple)):
|
||||||
if 'userName' in parts:
|
taskIds = [taskIds]
|
||||||
kw['userName'] = parts['userName'].comparisonValue
|
tasks = [util.getObjectForUid(t) for t in taskIds]
|
||||||
wi = self.workItems
|
for t in list(tasks):
|
||||||
return wi.query(**kw)
|
tasks.extend(self.getAllSubtasks(t))
|
||||||
|
return tasks
|
||||||
|
|
||||||
def getAllSubtasks(self, concept):
|
def getAllSubtasks(self, concept):
|
||||||
result = []
|
result = []
|
||||||
|
@ -208,12 +210,42 @@ class WorkReportInstance(ReportInstance):
|
||||||
result.extend(self.getAllSubtasks(c))
|
result.extend(self.getAllSubtasks(c))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def selectWorkItems(self, task, parts):
|
||||||
|
# TODO: take states from parts
|
||||||
|
kw = dict(task=util.getUidForObject(task), state=self.states)
|
||||||
|
if 'userName' in parts:
|
||||||
|
kw['userName'] = parts['userName'].comparisonValue
|
||||||
|
wi = self.workItems
|
||||||
|
return wi.query(**kw)
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def taskTypes(self):
|
def taskTypes(self):
|
||||||
return (self.conceptManager['task'],
|
return [c for c in [self.conceptManager.get(name)
|
||||||
self.conceptManager['event'],
|
for name in self.taskTypeNames]
|
||||||
self.conceptManager['project'])
|
if c is not None]
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def workItems(self):
|
def workItems(self):
|
||||||
return IWorkItems(self.recordManager['work'])
|
return IWorkItems(self.recordManager['work'])
|
||||||
|
|
||||||
|
|
||||||
|
# meeting minutes
|
||||||
|
|
||||||
|
class TaskRow(BaseRow):
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MeetingMinutes(WorkReportInstance):
|
||||||
|
|
||||||
|
type = "meeting_minutes"
|
||||||
|
label = u'Meeting Minutes'
|
||||||
|
|
||||||
|
rowFactory = TaskRow
|
||||||
|
|
||||||
|
fields = Jeep((tasks, title, description))
|
||||||
|
defaultOutputFields = fields
|
||||||
|
|
||||||
|
def selectObjects(self, parts):
|
||||||
|
return self.getTasks(parts)[1:]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue