You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
9.5 KiB

  1. from openerp.osv import osv,fields as old_fields
  2. from openerp import api, models, fields, tools
  3. from openerp.tools.safe_eval import safe_eval
  4. from openerp.addons.email_template.email_template import mako_template_env
  5. import copy
  6. from openerp.tools.translate import _
  7. class mail_wall_widgets_widget(models.Model):
  8. _name = 'mail.wall.widgets.widget'
  9. _order = "sequence, id"
  10. _columns = {
  11. 'name': old_fields.char('Name', required=True, translate=True),
  12. 'type': old_fields.selection(string='Type', selection=[
  13. ('list', 'List'),
  14. ('funnel', 'Funnel'),
  15. ('slice', 'Slice'),
  16. #('', ''),
  17. #('', ''),
  18. #('', ''),
  19. #('', ''),
  20. ], help='''
  21. Slice - use "domain" for total and "won_domain" for target
  22. '''),
  23. 'description': old_fields.text('Description', translate=True),
  24. 'group_ids': old_fields.many2many('res.groups', relation='mail_wall_widgets_widget_group', column1='widget_id', column2='group_id', string='Groups', help="User groups to show widget"),
  25. 'model_id': old_fields.many2one('ir.model', string='Model', help='The model object for the field to evaluate'),
  26. 'domain': old_fields.char("Filter Domain", help="Domain for filtering records. General rule, not user depending, e.g. [('state', '=', 'done')]. The expression can contain reference to 'user' which is a browse record of the current user if not in batch mode.", required=True),
  27. 'limit': old_fields.integer('Limit', help='Limit count of records to show'),
  28. 'order': old_fields.char('Order', help='Order of records to show'),
  29. 'value_field_id': old_fields.many2one('ir.model.fields',
  30. string='Value field',
  31. help='The field containing the value of record'),
  32. 'stage_field_id': old_fields.many2one('ir.model.fields',
  33. string='Stage field',
  34. help='Field to split records in funnel. It can be selection type or many2one (the later should have "sequence" field)'),
  35. #'stage_field_domain': old_fields.many2one('ir.model.fields',
  36. # string='Stage field domain',
  37. # help='(for many2one stage_field_id) Domain to find stage objects'),
  38. 'won_domain': old_fields.char('Won domain',
  39. help='Domain to find won objects'),
  40. 'field_date_id': old_fields.many2one('ir.model.fields',
  41. string='Date Field',
  42. help='The date to use for the time period evaluated'),
  43. 'start_date': old_fields.date('Start Date'),
  44. 'end_date': old_fields.date('End Date'), # no start and end = always active
  45. 'content': old_fields.char('Line template', help='Mako template to show content'),
  46. 'value_field_monetary': old_fields.boolean('Value is monetary'),
  47. 'cache': old_fields.boolean('Cache'),
  48. 'active': old_fields.boolean('Active'),
  49. 'sequence': old_fields.integer('Sequence', help='Sequence number for ordering'),
  50. }
  51. _defaults = {
  52. 'active': True,
  53. 'cache': False,
  54. 'limit': None,
  55. 'order': None,
  56. }
  57. @api.one
  58. def get_data(self, user):
  59. domain = safe_eval(self.domain, {'user': user})
  60. won_domain = safe_eval(self.won_domain or '[]', {'user': user})
  61. field_date_name = self.field_date_id and self.field_date_id.name
  62. if self.start_date and field_date_name:
  63. domain.append((field_date_name, '>=', self.start_date))
  64. if self.end_date and field_date_name:
  65. domain.append((field_date_name, '<=', self.end_date))
  66. res = {
  67. 'name': self.name,
  68. 'type': self.type,
  69. 'model': self.model_id.model,
  70. 'domain': str(domain),
  71. }
  72. obj = self.env[self.model_id.model]
  73. if self.type == 'list':
  74. total_count = obj.search_count(domain)
  75. res.update({
  76. 'more': self.limit and self.limit < total_count,
  77. 'total_count': total_count,
  78. 'lines': [],
  79. })
  80. for r in obj.search(domain, limit=self.limit, order=self.order):
  81. mako = mako_template_env.from_string(tools.ustr(self.content))
  82. content = mako.render({'record':r})
  83. r_json = {
  84. 'id': r.id,
  85. #'fields': dict( (f,getattr(r,f)) for f in fields),
  86. 'display_mode': 'progress',
  87. 'state': 'inprogress',
  88. 'completeness': 0,
  89. 'name': content,
  90. 'description': '',
  91. }
  92. if self.value_field_id:
  93. r_json['current'] = getattr(r, self.value_field_id.name)
  94. res['lines'].append(r_json)
  95. elif self.type == 'funnel':
  96. stage_ids = [] # [key]
  97. for group in obj.read_group(domain, [], [self.stage_field_id.name]):
  98. key = group[self.stage_field_id.name]
  99. if isinstance(key, (list, tuple)):
  100. key = key[0]
  101. stage_ids.append(key)
  102. stages = [] # [{'name':Name, 'id': key}]
  103. if self.stage_field_id.ttype == 'selection':
  104. d = dict (self.stage_field_id.selection)
  105. stages = [ {'id':id, 'name':d[id]} for id in stage_ids ]
  106. else: # many2one
  107. stage_model = self.stage_field_id.relation
  108. for r in self.env[stage_model].browse(stage_ids):
  109. stages.append({'id': r.id, 'name':r.name_get()[0][1]})
  110. value_field_name = self.value_field_id.name
  111. for stage in stages:
  112. d = copy.copy(domain)
  113. d.append( (self.stage_field_id.name, '=', stage['id']) )
  114. result = obj.read_group(d, [value_field_name], [])
  115. stage['closed_value'] = result and result[0][value_field_name] or 0.0
  116. stage['domain'] = str(d)
  117. # won value
  118. d = domain + won_domain
  119. result = obj.read_group(domain, [value_field_name], [])
  120. won = {'name': _('Won'),
  121. 'id':'__won__',
  122. 'closed_value': result and result[0][value_field_name] or 0.0
  123. }
  124. stages.append(won)
  125. cur = 0
  126. for stage in reversed(stages):
  127. cur += stage['closed_value']
  128. stage['abs_value'] = cur
  129. total_value = stages[0]['abs_value']
  130. precision = 0.1
  131. for s in stages:
  132. s['rel_value'] = round(100*s['abs_value']/total_value/precision)*precision if total_value else 100
  133. # dummy fields
  134. s['display_mode'] = 'progress'
  135. s['monetary'] = 1
  136. res['stages'] = stages
  137. res['won'] = won
  138. res['conversion_rate'] = stages[-1]['rel_value']
  139. elif self.type == 'slice':
  140. value_field_name = self.value_field_id.name
  141. for f,d in [('total', domain), ('won', won_domain)]:
  142. result = obj.read_group(d, [value_field_name], [])
  143. res[f] = result and result[0][value_field_name] or 0.0
  144. res['domain'] = str(domain)
  145. res['won_domain'] = str(won_domain)
  146. precision = 10
  147. total_value = res['total']
  148. res['slice'] = round(100*res['won']/res['total']/precision)*precision if res['total'] else 100
  149. # dummy fields
  150. res['display_mode'] = 'progress'
  151. res['monetary'] = self.value_field_monetary
  152. return res
  153. class mail_wall_widgets_cache(models.Model):
  154. _name = 'mail.wall.widgets.cache'
  155. cache = fields.Text('Cached data')
  156. res_id = fields.Integer('Resource ID')
  157. res_model = fields.Integer('Resource Model')
  158. user_id = fields.Many2one('res.users')
  159. class res_users(models.Model):
  160. _inherit = 'res.users'
  161. @api.v7
  162. def get_serialised_mail_wall_widgets_summary(self, cr, uid, excluded_categories=None, context=None):
  163. return self._get_serialised_mail_wall_widgets_summary(cr, uid, uid, excluded_categories=excluded_categories, context=context)[0]
  164. @api.one
  165. def _get_serialised_mail_wall_widgets_summary(self, excluded_categories=None):
  166. """
  167. [
  168. {
  169. 'id': ...,
  170. 'model': ...,
  171. 'currency': <res.currency id>,
  172. 'data': (depend on model)
  173. },
  174. ]
  175. """
  176. user = self.env.user
  177. res = []
  178. model = 'mail.wall.widgets.widget'
  179. domain = [('group_ids', 'in', user.groups_id.ids), ('active', '=', True)]
  180. for widget in self.env[model].search(domain, order='sequence'):
  181. if widget.cache:
  182. #TODO
  183. continue
  184. res.append({
  185. 'model': model,
  186. 'id': widget.id,
  187. 'currency': user.company_id.currency_id.id,
  188. 'data': widget.get_data(user)[0],
  189. })
  190. return res
  191. #def get_challenge_suggestions(self, cr, uid, context=None):
  192. # """Return the list of challenges suggested to the user"""
  193. # challenge_info = []
  194. # challenge_obj = self.pool.get('mail_wall_widgets.challenge')
  195. # challenge_ids = challenge_obj.search(cr, uid, [('invited_user_ids', 'in', uid), ('state', '=', 'inprogress')], context=context)
  196. # for challenge in challenge_obj.browse(cr, uid, challenge_ids, context=context):
  197. # values = {
  198. # 'id': challenge.id,
  199. # 'name': challenge.name,
  200. # 'description': challenge.description,
  201. # }
  202. # challenge_info.append(values)
  203. # return challenge_info