[Erp5-report] r7379 - /erp5/trunk/products/ERP5Form/PlanningBox.py

nobody at svn.erp5.org nobody at svn.erp5.org
Mon May 22 10:25:10 CEST 2006


Author: thomas
Date: Mon May 22 10:25:05 2006
New Revision: 7379

URL: http://svn.erp5.org?rev=7379&view=rev
Log:
Improved axis generator with more spacers
fixed bug about tooltiptext on axis : now handle correctly
full title over main & secondary axis.


Modified:
    erp5/trunk/products/ERP5Form/PlanningBox.py

Modified: erp5/trunk/products/ERP5Form/PlanningBox.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Form/PlanningBox.py?rev=7379&r1=7378&r2=7379&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Form/PlanningBox.py (original)
+++ erp5/trunk/products/ERP5Form/PlanningBox.py Mon May 22 10:25:05 2006
@@ -512,8 +512,11 @@
   ['representation_type','main_axis_groups','size_header_height', 'size_border_width_left',
    'size_planning_width', 'size_y_axis_width','size_y_axis_space','size_planning_height','size_x_axis_height',
    'size_x_axis_space', 'y_axis_position', 'x_axis_position', 'delimiter',
-   'list_method','report_root_list','selection_name',
-   'portal_types','sort','title_line','x_start_bloc','x_stop_bloc',
+   'report_root_list','selection_name',
+   'portal_types','sort',
+   'list_method',
+   'stat_method',
+   'title_line','x_start_bloc','x_stop_bloc',
    'y_axis_method','constraint_method','split_method','color_script',
    'round_script','sec_axis_script','info_center',
    'info_topleft','info_topright','info_backleft','info_backright',
@@ -667,6 +670,12 @@
       default='',
       required=0)
 
+  stat_method = fields.StringField('stat_method',
+      title="specific method used to generate statistics:",
+      description=("specific method for statistics"),
+      default='',
+      required=0)
+
   title_line = fields.StringField('title_line',
       title="specific method which fetches the title of each line: ",
       description=("specific method for inserting title in line"),
@@ -688,13 +697,13 @@
       description=('Property for building X-Axis such as stop_date\
       objects'),
       default='stop_date',
-      required=0)	
+      required=0)
 
   y_axis_method = fields.StringField('y_axis_method',
       title='specific method of data type for creating height of blocks',
       description=('Method for building height of blocks objects'),
       default='',
-      required=0) 
+      required=0)
 
 
   constraint_method = fields.StringField('constraint_method',
@@ -733,7 +742,7 @@
       description=('Method for displaying info in the center of a\
       block object'),
       default='',
-      required=0) 
+      required=0)
 
   info_topright = fields.StringField('info_topright',
       title='specific method of data called for inserting info in\
@@ -843,8 +852,6 @@
 
     # DATA DEFINITION
 
-
-    
 
     # recovering usefull planning properties
     form = field.aq_parent # getting form
@@ -1029,6 +1036,35 @@
       self.list_method = None
 
 
+    ##################################################
+    ############## DEFINING STAT METHOD ##############
+    ##################################################
+    # XXX implementing this new functionality
+    #pdb.set_trace()
+    stat_method = self.field.get_value('stat_method')
+
+    if hasattr(stat_method, 'method_name'):
+      if stat_method.method_name == 'objectValues':
+        stat_method = None # Nothing to do in this case
+        show_stat = 0
+      elif stat_method.method_name == 'portal_catalog':
+        # We use the catalog count results
+        stat_method = here.portal_catalog.countResults
+        show_stat = 1
+      else:
+        # Try to get the method through acquisition
+        try:
+          stat_method = getattr(here, stat_method.method_name)
+          show_stat = 1
+        except (AttributeError, KeyError):
+          show_stat = 0
+          pass
+    else:
+      # No stat method defined means no statistics displayed
+      stat_method = None
+      show_stat = 0
+
+
 
     ##################################################
     ############ BUILDING REPORT_TREE ################
@@ -1061,6 +1097,8 @@
      report_depth=report_depth,is_report_opened=is_report_opened,
      sort_on=self.selection.sort_on,form_id=self.form.id)
 
+    # XXX fixing bug with make tree-list, unfolding reports to the 'n+1' level.
+    # report_list is now built from the report_group list.
     #report_list = map(lambda s:s.getObject().getRelativeUrl(), report_tree_list)
     #self.selection.edit(report_list=report_list)
 
@@ -1087,24 +1125,36 @@
     select_expression = ''
 
 
+
+    #pdb.set_trace()
     # now iterating through object_tree_list
+
+
+    """
     for object_tree_line in report_tree_list:
       # prepare query by defining selection report object
       self.selection.edit(report = object_tree_line.getSelectDomainDict())
 
-      if object_tree_line.getIsPureSummary():
+      #if object_tree_line.getIsPureSummary():
+
+
+      if (object_tree_line.getIsPureSummary() and \
+         selection_report_path=='parent'):
+
+
         # push new select_expression
         original_select_expression = kw.get('select_expression')
         kw['select_expression'] = select_expression
         self.selection.edit(params = kw)
+        # XXX recovering statistics (will use them afterwards if necessary)
+        #stat_temp = self.selection(method = stat_method, context=self.here, REQUEST=self.REQUEST)
         # pop new select_expression
         if original_select_expression is None:
           del kw['select_expression']
         else:
           kw['select_expression'] = original_select_expression
 
-      if (object_tree_line.getIsPureSummary() and \
-         selection_report_path=='parent'):
+
         # object_tree_line is Pure summary : does not have any activity
         stat_result = {}
         index=1
@@ -1114,8 +1164,9 @@
         self.report_groups += [object_tree_line]
         self.nbr_groups = self.nbr_groups + 1
 
+
         # resetting original value
-        self.selection.edit(report = None)
+        #self.selection.edit(report = None)
       else:
         # object_tree_line is not pure summary : it has activities
         # prepare query
@@ -1127,7 +1178,7 @@
           self.selection.edit(exception_uid_list= \
              object_tree_line.getExceptionUidList())
           object_list = self.selection(method = self.list_method,
-             context=self.here, REQUEST=self.REQUEST)    
+             context=self.here, REQUEST=self.REQUEST)
         else:
           # no list_method found
           object_list = self.here.portal_selections.getSelectionValueList(
@@ -1183,19 +1234,130 @@
 
         # resetting original value
         self.selection.edit(report = None)
-
-    self.selection.edit(report=None)
+    """
+
+    # XXX just for testing
+    show_stat = 0
+
+    for object_tree_line in report_tree_list:
+      # prepare query by defining selection report object
+      self.selection.edit(report = object_tree_line.getSelectDomainDict())
+
+      # defining info_dict, holding all information about the current object.
+      info_dict = None
+      info_dict = {}
+
+      if object_tree_line.getIsPureSummary() and show_stat:
+
+        info_dict['stat'] = 1
+
+        # push new select_expression
+        original_select_expression = kw.get('select_expression')
+        kw['select_expression'] = select_expression
+        self.selection.edit(params = kw)
+        # XXX recovering statistics
+        # need to recover a list of temporary objects
+        # should be improved to take several more parameters into account
+        #stat_list = self.selection(method = stat_method, context=self.here, REQUEST=self.REQUEST)
+        stat_list = self.stat_method(selection= self.selection, report_tree_list=report_tree_list, object_tree_line= object_tree_line, context=self.here, REQUEST=self.REQUEST)
+        # pop new select_expression
+        if original_select_expression is None:
+          del kw['select_expression']
+        else:
+          kw['select_expression'] = original_select_expression
+
+        # adding current line to report_section where
+        # line is pure Summary
+        self.report_groups += [(object_tree_line,stat_list,info_dict)]
+        self.nbr_groups += 1
+
+      else:
+        info_dict['stat'] = 0
+
+        # processing all cases
+        self.selection.edit(params = kw)
+
+        # recovering object list
+        if self.list_method not in (None,''):
+          # valid list_method has been found
+          self.selection.edit(exception_uid_list= \
+             object_tree_line.getExceptionUidList())
+          object_list = self.selection(method = self.list_method,
+             context=self.here, REQUEST=self.REQUEST)
+        else:
+          # no list_method found
+          object_list = self.here.portal_selections.getSelectionValueList(
+            self.selection_name, context=self.here, REQUEST=self.REQUEST)
+
+        # recovering exeption_uid_list
+        exception_uid_list = object_tree_line.getExceptionUidList()
+        if exception_uid_list not in (None,()):
+          # Filter folders if parent tree :
+          # build new object_list for current line
+          # (list of relative elements)
+          new_object_list = []
+          for selected_object in object_list:
+            if selected_object.getUid() not in exception_uid_list:
+              new_object_list.append(selected_object)
+          object_list = new_object_list
+
+        if not object_tree_line.getIsPureSummary():
+          # Object is not pure summary
+          if show_stat:
+            # this represents the second duplicated object
+            # display object content in report tree with stat
+            # stats are displayed in the first object present
+            #
+            self.report_groups += [(object_tree_line,object_list, info_dict)]
+            self.nbr_groups += 1
+          else:
+            # do nothing
+            # case of parent tree unfolded (second object and no stats)
+            pass
+        else:
+          # object is pure summary !
+
+          # XXX useless as properties are recovered while creating AxisGroup
+          # recovering object_line properties to display good link
+          #stat_context = object_tree_line.getObject().asContext()
+          #stat_context.absolute_url = object_tree_line.getObject().absolute_url()
+          #stat_context.domain_url = object_tree_line.getObject().getRelativeUrl()
+
+          if len(object_list) and object_tree_line.is_open:
+            # pure summary, open, and has object_list
+            # case = ?!?
+            self.report_groups += [(object_tree_line, object_list, info_dict)]
+            self.nbr_groups += 1
+          else:
+            if exception_uid_list is not None:
+              # case of parent tree mode (first/unique object).
+              # beware object_list is not null in case folded sons exists so
+              # do not export voluntary object_list to prevent bad interpretation
+              self.report_groups += [(object_tree_line, [], info_dict)]
+              self.nbr_groups += 1
+            else:
+              # case of report_tree mode
+              # saving information in report_groups
+              self.report_groups += [(object_tree_line,object_list,info_dict)]
+              self.nbr_groups += 1
+
+
+
+    # reset to original value
+    self.selection.edit(report = None)
+
     self.selection.edit(report_list=None)
-    LOG('self.report_activity_dict',0,self.report_activity_dict)
+    #LOG('self.report_activity_dict',0,self.report_activity_dict)
 
 
     #pdb.set_trace()
     # update report list if report_depth was specified
     if report_depth is not None:
       unfolded_list = []
-      for report_line in self.report_groups:
-        if report_line.depth < report_depth:
+      for (report_line, object_list, info_dict) in self.report_groups:
+        if report_line.depth < report_depth and not info_dict['stat'] :
           # depth of current report_line is inferior to the current report_depth
+          # and current report_line is not stat line. saving information
           unfolded_list.append(report_line.getObject().getRelativeUrl())
       self.selection.edit(report_list=unfolded_list)
 
@@ -1259,6 +1421,46 @@
     return 1
 
 
+  def stat_method(self, selection=None, report_tree_list = None, object_tree_line=None, context=None, REQUEST=None):
+    """
+    XXX temporary function to recover statistics when needed
+    returns a list with temporary objects
+    """
+    from Products.ERP5Type.Document import newTempBase
+
+
+    # first recovering methods to apply on tasks
+    start_property_id = self.field.get_value('x_start_bloc')
+    stop_property_id= self.field.get_value('x_stop_bloc')
+
+    # XXX need to find a way to get all related objects with their sub-objects
+    # this list of objects must be stored in a list
+    # for now considering applying statistics on object_list
+    self.selection.edit(exception_uid_list= object_tree_line.getExceptionUidList())
+    input_object_list = self.selection(method = self.list_method,context=self.here,
+                                      REQUEST=self.REQUEST)
+
+
+    temp_object_list = []
+    temp_object_id = 0
+    # now applying statictic rule.
+    # for now statistic rules are static
+    for input_object in input_object_list:
+      # recovering input_object attributes
+      block_begin = input_object.getObject().getProperty(start_property_id)
+      block_end = input_object.getObject().getProperty(stop_property_id)
+      # creating new object
+      temp_object = newTempBase(context.getPortalObject(),temp_object_id)
+      # editing object with new values
+      setattr(temp_object,start_property_id,block_begin)
+      setattr(temp_object,stop_property_id, block_end)
+      # adding new object to list
+      temp_object_list.append(temp_object)
+      temp_object_id += 1
+
+    return temp_object_list
+
+
   def getSecondaryAxisOccurence(self):
     """
     get secondary_axis occurences in order to define begin and end bounds
@@ -1268,37 +1470,48 @@
     # specific start & stop methods name for secondary axis
     start_property_id = self.field.get_value('x_start_bloc')
     stop_property_id= self.field.get_value('x_stop_bloc')
-    for object_tree_group in self.report_groups:
+    for (object_tree_group, object_list, info_dict) in self.report_groups:
       # recover method to et begin and end limits
-      
-
-      try:
-        child_activity_list = self.report_activity_dict[object_tree_group.getObject().getTitle()]
-      except (AttributeError, KeyError):
-        child_activity_list = None
+
+
+      #try:
+      #  child_activity_list = self.report_activity_dict[object_tree_group.getObject().getTitle()]
+      #except (AttributeError, KeyError):
+      #  child_activity_list = None
 
       #if method_start == None and child_activity_list != None:
-      if child_activity_list not in (None, [], {}):
-        # can not recover method from object_tree_group itself, trying
-        # over the activity list
-        # XXX in fact can not fail to recover method from object_tree_group
-        # get : <bound method ImplicitAcquirerWrapper.(?) of <Project at /erp5/project_module/planning>>
-        # so just trying if children exist
-        for child_activity in child_activity_list:
-          
-          if start_property_id != None:
-            block_begin = child_activity.getObject().getProperty(start_property_id)
-          else:
-            block_begin = None
-
-          if stop_property_id != None:
-            block_stop = child_activity.getObject().getProperty(stop_property_id)
-          else:
-            block_stop = None
-
-          secondary_axis_occurence.append([block_begin,block_stop])
+      if object_list not in (None, [], {}) :
+        if not info_dict['stat']:
+          for object_request in object_list:
+
+            if start_property_id != None:
+              block_begin = object_request.getObject().getProperty(start_property_id)
+            else:
+              block_begin = None
+
+            if stop_property_id != None:
+              block_stop = object_request.getObject().getProperty(stop_property_id)
+            else:
+              block_stop = None
+            secondary_axis_occurence.append([block_begin,block_stop])
+        else:
+          # in case stat line
+          for temp_object in object_list:
+
+            if start_property_id != None:
+              block_begin = getattr(temp_object.getObject(),start_property_id)
+            else:
+              block_begin = None
+
+            if stop_property_id != None:
+              block_stop = getattr(temp_object.getObject(),stop_property_id)
+            else:
+              block_stop = None
+            secondary_axis_occurence.append([block_begin,block_stop])
 
       else:
+
+      #elif not info_dict['stat'] :
         # method sucessfully recovered
         # getting values
         if start_property_id != None:
@@ -1313,6 +1526,8 @@
 
         secondary_axis_occurence.append([block_begin,block_stop])
 
+
+
     return secondary_axis_occurence
 
 
@@ -1323,9 +1538,6 @@
     it is now possible to recover begin and end value of the planning and then
     apply selection informations to get start and stop.
     """
-
-    
-
 
     axis_dict['zoom_start'] = int(self.params.get('zoom_start',0))
     axis_dict['zoom_level'] = float(self.params.get('zoom_level',1))
@@ -1375,7 +1587,7 @@
     example).
     """
 
-    
+
     axis_dict['bound_axis_groups'] = self.field.get_value('main_axis_groups')
     if axis_dict['bound_axis_groups'] == None:
       #XXX raise exception : no group defined
@@ -1433,7 +1645,7 @@
       position = 0
 
       # iterating each element
-      for report_group_object in self.report_groups:
+      for (report_group_object, object_list, property_dict) in self.report_groups:
 
         stat_result = {}
         stat_context = report_group_object.getObject().asContext(**stat_result)
@@ -1446,20 +1658,21 @@
         title = report_group_object.getObject().getTitle()
         name = report_group_object.getObject().getTitle()
         depth = report_group_object.getDepth()
-        is_open = report_group_object.is_open
-        is_pure_summary = report_group_object.is_pure_summary
+        is_open = report_group_object.getIsOpen()
+        is_pure_summary = report_group_object.getIsPureSummary()
 
         # creating new group_object with all the informations collected
-        child_group = BasicGroup( title=title, name=name, url=url, constraints=None, depth=depth, position=position, field =self.field, object=report_group_object, is_open=is_open, is_pure_summary=is_pure_summary)
+        child_group = BasicGroup( title=title, name=name, url=url, constraints=None, depth=depth, position=position, field =self.field, object=report_group_object, is_open=is_open, is_pure_summary=is_pure_summary, property_dict = property_dict)
 
         # creating activities related to the new group
         # first recovering activity list if exists
-        report_activity_list = []
-        if title in self.report_activity_dict.keys():
-          report_activity_list = self.report_activity_dict[title]
+        #report_activity_list = []
+        #if title in self.report_activity_dict.keys():
+        #  report_activity_list = self.report_activity_dict[title]
         # linking activities to the bloc. the parameter is a list of elements
         # to link to the child_group object.
-        child_group.setBasicActivities(report_activity_list,self.list_error,self.secondary_axis_info)
+        if object_list != None:
+          child_group.setBasicActivities(object_list,self.list_error,self.secondary_axis_info)
 
         try:
           self.basic_group_list.append(child_group)
@@ -1480,7 +1693,7 @@
   ReportTree mode to handle child groups.
   """
 
-  def __init__ (self, title='', name='',url='', constraints='', depth=0, position=0, field = None, object = None, is_open=0, is_pure_summary=1):
+  def __init__ (self, title='', name='',url='', constraints='', depth=0, position=0, field = None, object = None, is_open=0, is_pure_summary=1, property_dict = {}):
     self.title = title
     self.name = name
     self.url = url
@@ -1499,6 +1712,10 @@
     self.start = None
     self.stop = None
 
+    # property_dict holds all information about the current axis_group
+    # type of group, stat, etc.
+    self.property_dict = property_dict
+
 
   def setBasicActivities(self,activity_list, list_error,secondary_axis_info):
     """
@@ -1572,7 +1789,7 @@
           block_end = None
 
 
-        # ahndling case where activity bound is not defined
+        # handling case where activity bound is not defined
         if block_begin == None:
           block_begin = secondary_axis_info['bound_start']
           current_color='#E4CCE1'
@@ -2053,11 +2270,12 @@
     #if split_method != None:
     #  secondary_block_bounds = split_method(self.secondary_axis_start, self.secondary_axis_stop)
     else:
-      secondary_block_bounds = [[self.secondary_axis_start,self.secondary_axis_stop]]
+      secondary_block_bounds = [[self.secondary_axis_start,self.secondary_axis_stop,1]]
 
     block_number = 0
     # iterating resulting list
-    for (start,stop) in secondary_block_bounds:
+    #pdb.set_trace()
+    for (start,stop,zone) in secondary_block_bounds:
 
       block_number += 1
 
@@ -2071,7 +2289,13 @@
         error = 0
         error_text=''
 
-      new_block = Bloc(name= block_name,color=self.color,link=self.link, number = block_number, render_format=self.render_format, parent_activity=self, warning=warning, error=error, error_text=error_text)
+      if zone == 1:
+        block_color = ''
+        block_link = self.link
+      else:
+        block_color = '#D1E8FF'
+        block_link = ''
+      new_block = Bloc(name= block_name,color=block_color,link=block_link, number = block_number, render_format=self.render_format, parent_activity=self, warning=warning, error=error, error_text=error_text,zone=zone)
 
 
       new_block.buildInfoDict(info_dict = self.info)
@@ -2131,7 +2355,64 @@
            will use an external script to do so.
     """
     # XXX not implemented yet
-    return [(self.secondary_axis_start,self.secondary_axis_stop)]
+    return [(self.secondary_axis_start,self.secondary_axis_stop,1)]
+
+    #XXX current script cuts activities into several blocks representing the worked days
+
+
+    returned_list = []
+
+
+    start_date = self.secondary_axis_start
+    stop_date = self.secondary_axis_stop
+
+    temp_start = start_date
+    temp_stop  = temp_start
+
+    # defining usefull list of data
+    break_list = ['Saturday','Sunday']
+    worked_list = ['Monday','Tuesday','Wednesday','Thursday','Friday']
+    switch_list = ['Monday','Saturday']
+
+    if temp_start.Day() in break_list:
+      # temp_start is in weekend,
+      # getting first worked day
+      while temp_start.Day() in break_list and temp_start < stop_date:
+        temp_start += 1
+      returned_list.append([temp_stop,temp_start,0])
+    else:
+      # temp_stop is in week, getting first weekend
+      while temp_stop.Day() in worked_list and temp_stop < stop_date:
+        temp_stop += 1
+      if temp_stop > stop_date:
+        temp_stop = stop_date
+
+    # testing if current activity is not too small to create blocks
+    while temp_start < stop_date:
+      returned_list.append([temp_start,temp_stop,1])
+
+      temp_start = temp_stop
+      # going to next start_date
+      while temp_start.Day() in break_list and temp_start < stop_date:
+        temp_start += 1
+
+      # adding new start date to list
+      if temp_start >= stop_date:
+        returned_list.append([temp_stop,stop_date,0])
+      elif temp_start != temp_stop:
+        returned_list.append([temp_stop,temp_start,0])
+      # next temp_start has been found
+      # now processing new temp_stop
+      temp_stop = temp_start
+      while temp_stop.Day() in worked_list and temp_stop < stop_date:
+        temp_stop += 1
+      if temp_stop > stop_date:
+        temp_stop = stop_date
+
+    # return new list
+    return returned_list
+
+
 
 
 
@@ -2150,7 +2431,7 @@
                 color=None, info=None, link=None, number=0,
                 constraints=None, secondary_start=None, secondary_stop=None,
                 render_format='YX', parent_activity = None, warning=0, error=0,
-                error_text=''):
+                error_text='', zone=1):
     """
     creates a Bloc object
     """
@@ -2161,6 +2442,7 @@
     self.link = link # on clic link
     self.number = number
     self.title=''
+    self.zone = zone
     self.parent_activity = parent_activity
     self.constraints = constraints
     # setting warning and error flags in case parent_activity or block itself
@@ -2316,6 +2598,7 @@
     using actual AxisGroup properties to define some special comportement that
     the axisGroup should have, especially in case of report-tree
     """
+
     if self.is_open:
       # current report is unfold, action 'fold'
       self.info_title.link = 'portal_selections/foldReport?report_url=' + self.url + '&form_id='+ form_id + '&list_selection_name=' + selection_name
@@ -2325,11 +2608,11 @@
       self.info_title.link = 'portal_selections/unfoldReport?report_url=' + self.url + '&form_id='+ form_id + '&list_selection_name=' + selection_name
       self.info_title.info = '[+] ' + self.info_title.info
 
-
     #for i in range(self.depth):
     #  self.title = '| ' + self.title
-
     self.info_title.title = self.info_title.info
+    
+    self.tooltip = self.info_title.info
 
 
   def addActivity(self, activity=None, axis_element_already_insered= 0):




More information about the Erp5-report mailing list