sobjects/supervising.py
branchtls-sprint
changeset 1723 30c3a713ab61
parent 1398 5fe84a5f7035
child 1977 606923dff11b
equal deleted inserted replaced
1722:62f3fefb22f4 1723:30c3a713ab61
    17 
    17 
    18 class SomethingChangedHook(Hook):
    18 class SomethingChangedHook(Hook):
    19     events = ('before_add_relation', 'before_delete_relation',
    19     events = ('before_add_relation', 'before_delete_relation',
    20               'after_add_entity', 'before_update_entity')
    20               'after_add_entity', 'before_update_entity')
    21     accepts = ('Any',)
    21     accepts = ('Any',)
    22     
    22 
    23     def call(self, session, *args):
    23     def call(self, session, *args):
    24         dest = self.config['supervising-addrs']
    24         dest = self.config['supervising-addrs']
    25         if not dest: # no supervisors, don't do this for nothing...
    25         if not dest: # no supervisors, don't do this for nothing...
    26             return
    26             return
    27         self.session = session
    27         self.session = session
    28         if self._call(*args):
    28         if self._call(*args):
    29             SupervisionMailOp(session)
    29             SupervisionMailOp(session)
    30         
    30 
    31     def _call(self, *args):
    31     def _call(self, *args):
    32         if self._event() == 'update_entity' and args[0].e_schema == 'CWUser':
    32         if self._event() == 'update_entity' and args[0].e_schema == 'CWUser':
    33             updated = set(args[0].iterkeys())
    33             updated = set(args[0].iterkeys())
    34             if not (updated - frozenset(('eid', 'modification_date', 'last_login_time'))):
    34             if not (updated - frozenset(('eid', 'modification_date', 'last_login_time'))):
    35                 # don't record last_login_time update which are done 
    35                 # don't record last_login_time update which are done
    36                 # automatically at login time
    36                 # automatically at login time
    37                 return False
    37                 return False
    38         self.session.add_query_data('pendingchanges', (self._event(), args))
    38         self.session.add_query_data('pendingchanges', (self._event(), args))
    39         return True
    39         return True
    40         
    40 
    41     def _event(self):
    41     def _event(self):
    42         return self.event.split('_', 1)[1]
    42         return self.event.split('_', 1)[1]
    43 
    43 
    44 
    44 
    45 class EntityDeleteHook(SomethingChangedHook):
    45 class EntityDeleteHook(SomethingChangedHook):
    46     events = ('before_delete_entity',)
    46     events = ('before_delete_entity',)
    47     
    47 
    48     def _call(self, eid):
    48     def _call(self, eid):
    49         entity = self.session.entity(eid)
    49         entity = self.session.entity(eid)
    50         try:
    50         try:
    51             title = entity.dc_title()
    51             title = entity.dc_title()
    52         except:
    52         except:
    78             added.add(entity.eid)
    78             added.add(entity.eid)
    79             if entity.e_schema == 'TrInfo':
    79             if entity.e_schema == 'TrInfo':
    80                 changes.remove(change)
    80                 changes.remove(change)
    81                 if entity.from_state:
    81                 if entity.from_state:
    82                     try:
    82                     try:
    83                         changes.remove( ('delete_relation', 
    83                         changes.remove( ('delete_relation',
    84                                          (entity.wf_info_for[0].eid, 'in_state', 
    84                                          (entity.wf_info_for[0].eid, 'in_state',
    85                                           entity.from_state[0].eid)) )
    85                                           entity.from_state[0].eid)) )
    86                     except ValueError:
    86                     except ValueError:
    87                         pass
    87                         pass
    88                     try:
    88                     try:
    89                         changes.remove( ('add_relation', 
    89                         changes.remove( ('add_relation',
    90                                          (entity.wf_info_for[0].eid, 'in_state', 
    90                                          (entity.wf_info_for[0].eid, 'in_state',
    91                                           entity.to_state[0].eid)) )
    91                                           entity.to_state[0].eid)) )
    92                     except ValueError:
    92                     except ValueError:
    93                         pass
    93                         pass
    94                     event = 'change_state'
    94                     event = 'change_state'
    95                     change = (event, 
    95                     change = (event,
    96                               (entity.wf_info_for[0],
    96                               (entity.wf_info_for[0],
    97                                entity.from_state[0], entity.to_state[0]))
    97                                entity.from_state[0], entity.to_state[0]))
    98                     changes.append(change)
    98                     changes.append(change)
    99         elif event == 'delete_entity':
    99         elif event == 'delete_entity':
   100             deleted.add(changedescr[0])
   100             deleted.add(changedescr[0])
   113                 # skip in_state relation if the entity is being created
   113                 # skip in_state relation if the entity is being created
   114                 # XXX this may be automatized by skipping all mandatory relation
   114                 # XXX this may be automatized by skipping all mandatory relation
   115                 #     at entity creation time
   115                 #     at entity creation time
   116                 elif changedescr[1] == 'in_state' and changedescr[0] in added:
   116                 elif changedescr[1] == 'in_state' and changedescr[0] in added:
   117                     index['add_relation'].remove(change)
   117                     index['add_relation'].remove(change)
   118                     
   118 
   119         except KeyError:
   119         except KeyError:
   120             break
   120             break
   121     for eid in deleted:
   121     for eid in deleted:
   122         try:
   122         try:
   123             for change in index['delete_relation'].copy():
   123             for change in index['delete_relation'].copy():
   144     __select__ = none_rset()
   144     __select__ = none_rset()
   145     id = 'supervision_notif'
   145     id = 'supervision_notif'
   146 
   146 
   147     def recipients(self):
   147     def recipients(self):
   148         return self.config['supervising-addrs']
   148         return self.config['supervising-addrs']
   149         
   149 
   150     def subject(self):
   150     def subject(self):
   151         return self.req._('[%s supervision] changes summary') % self.config.appid
   151         return self.req._('[%s supervision] changes summary') % self.config.appid
   152     
   152 
   153     def call(self, changes):
   153     def call(self, changes):
   154         user = self.req.actual_session().user
   154         user = self.req.actual_session().user
   155         self.w(self.req._('user %s has made the following change(s):\n\n')
   155         self.w(self.req._('user %s has made the following change(s):\n\n')
   156                % user.login)
   156                % user.login)
   157         for event, changedescr in filter_changes(changes):
   157         for event, changedescr in filter_changes(changes):
   161 
   161 
   162     def _entity_context(self, entity):
   162     def _entity_context(self, entity):
   163         return {'eid': entity.eid,
   163         return {'eid': entity.eid,
   164                 'etype': entity.dc_type().lower(),
   164                 'etype': entity.dc_type().lower(),
   165                 'title': entity.dc_title()}
   165                 'title': entity.dc_title()}
   166     
   166 
   167     def add_entity(self, entity):
   167     def add_entity(self, entity):
   168         msg = self.req._('added %(etype)s #%(eid)s (%(title)s)')
   168         msg = self.req._('added %(etype)s #%(eid)s (%(title)s)')
   169         self.w(u'%s\n' % (msg % self._entity_context(entity)))
   169         self.w(u'%s\n' % (msg % self._entity_context(entity)))
   170         self.w(u'  %s' % entity.absolute_url())
   170         self.w(u'  %s' % entity.absolute_url())
   171             
   171 
   172     def update_entity(self, entity):
   172     def update_entity(self, entity):
   173         msg = self.req._('updated %(etype)s #%(eid)s (%(title)s)')
   173         msg = self.req._('updated %(etype)s #%(eid)s (%(title)s)')
   174         self.w(u'%s\n' % (msg % self._entity_context(entity)))
   174         self.w(u'%s\n' % (msg % self._entity_context(entity)))
   175         # XXX print changes
   175         # XXX print changes
   176         self.w(u'  %s' % entity.absolute_url())
   176         self.w(u'  %s' % entity.absolute_url())
   177             
   177 
   178     def delete_entity(self, eid, etype, title):
   178     def delete_entity(self, eid, etype, title):
   179         msg = self.req._('deleted %(etype)s #%(eid)s (%(title)s)')
   179         msg = self.req._('deleted %(etype)s #%(eid)s (%(title)s)')
   180         etype = display_name(self.req, etype).lower()
   180         etype = display_name(self.req, etype).lower()
   181         self.w(msg % locals())
   181         self.w(msg % locals())
   182         
   182 
   183     def change_state(self, entity, fromstate, tostate):
   183     def change_state(self, entity, fromstate, tostate):
   184         msg = self.req._('changed state of %(etype)s #%(eid)s (%(title)s)')
   184         msg = self.req._('changed state of %(etype)s #%(eid)s (%(title)s)')
   185         self.w(u'%s\n' % (msg % self._entity_context(entity)))
   185         self.w(u'%s\n' % (msg % self._entity_context(entity)))
   186         self.w(_('  from state %(fromstate)s to state %(tostate)s\n' % 
   186         self.w(_('  from state %(fromstate)s to state %(tostate)s\n' %
   187                  {'fromstate': _(fromstate.name), 'tostate': _(tostate.name)}))
   187                  {'fromstate': _(fromstate.name), 'tostate': _(tostate.name)}))
   188         self.w(u'  %s' % entity.absolute_url())
   188         self.w(u'  %s' % entity.absolute_url())
   189         
   189 
   190     def _relation_context(self, fromeid, rtype, toeid):
   190     def _relation_context(self, fromeid, rtype, toeid):
   191         _ = self.req._
   191         _ = self.req._
   192         session = self.req.actual_session()
   192         session = self.req.actual_session()
   193         def describe(eid):
   193         def describe(eid):
   194             try:
   194             try:
   200         return {'rtype': _(rtype),
   200         return {'rtype': _(rtype),
   201                 'fromeid': fromeid,
   201                 'fromeid': fromeid,
   202                 'frometype': describe(fromeid),
   202                 'frometype': describe(fromeid),
   203                 'toeid': toeid,
   203                 'toeid': toeid,
   204                 'toetype': describe(toeid)}
   204                 'toetype': describe(toeid)}
   205         
   205 
   206     def add_relation(self, fromeid, rtype, toeid):
   206     def add_relation(self, fromeid, rtype, toeid):
   207         msg = self.req._('added relation %(rtype)s from %(frometype)s #%(fromeid)s to %(toetype)s #%(toeid)s')
   207         msg = self.req._('added relation %(rtype)s from %(frometype)s #%(fromeid)s to %(toetype)s #%(toeid)s')
   208         self.w(msg % self._relation_context(fromeid, rtype, toeid))
   208         self.w(msg % self._relation_context(fromeid, rtype, toeid))
   209 
   209 
   210     def delete_relation(self, fromeid, rtype, toeid):
   210     def delete_relation(self, fromeid, rtype, toeid):
   211         msg = self.req._('deleted relation %(rtype)s from %(frometype)s #%(fromeid)s to %(toetype)s #%(toeid)s')
   211         msg = self.req._('deleted relation %(rtype)s from %(frometype)s #%(fromeid)s to %(toetype)s #%(toeid)s')
   212         self.w(msg % self._relation_context(fromeid, rtype, toeid))
   212         self.w(msg % self._relation_context(fromeid, rtype, toeid))
   213         
   213 
   214                 
   214 
   215 class SupervisionMailOp(SendMailOp):
   215 class SupervisionMailOp(SendMailOp):
   216     """special send email operation which should be done only once for a bunch
   216     """special send email operation which should be done only once for a bunch
   217     of changes
   217     of changes
   218     """
   218     """
   219     def _get_view(self):
   219     def _get_view(self):
   220         return self.session.vreg.select_component('supervision_notif',
   220         return self.session.vreg.select_component('supervision_notif',
   221                                                   self.session, None)
   221                                                   self.session, None)
   222         
   222 
   223     def _prepare_email(self):
   223     def _prepare_email(self):
   224         session = self.session
   224         session = self.session
   225         config = session.vreg.config
   225         config = session.vreg.config
   226         uinfo = {'email': config['sender-addr'],
   226         uinfo = {'email': config['sender-addr'],
   227                  'name': config['sender-name']}
   227                  'name': config['sender-name']}
   228         view = self._get_view()
   228         view = self._get_view()
   229         content = view.dispatch(changes=session.query_data('pendingchanges'))
   229         content = view.render(changes=session.query_data('pendingchanges'))
   230         recipients = view.recipients()
   230         recipients = view.recipients()
   231         msg = format_mail(uinfo, recipients, content, view.subject(), config=config)
   231         msg = format_mail(uinfo, recipients, content, view.subject(), config=config)
   232         self.to_send = [(msg, recipients)]
   232         self.to_send = [(msg, recipients)]
   233 
   233 
   234     def commit_event(self):
   234     def commit_event(self):