OCA reporting engine fork for dev and update.
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.

219 lines
7.8 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2015-2016 ONESTEiN BV (<http://www.onestein.eu>)
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from openerp import models, api
  5. from openerp.modules.registry import RegistryManager
  6. NO_BI_MODELS = [
  7. "temp.range",
  8. "account.statement.operation.template",
  9. "fetchmail.server"
  10. ]
  11. NO_BI_FIELDS = [
  12. "id",
  13. "create_uid",
  14. "create_date",
  15. "write_uid",
  16. "write_date"
  17. ]
  18. def dict_for_field(field):
  19. return {
  20. "id": field.id,
  21. "name": field.name,
  22. "description": field.field_description,
  23. "type": field.ttype,
  24. "relation": field.relation,
  25. "custom": False,
  26. "model_id": field.model_id.id,
  27. "model": field.model_id.model,
  28. "model_name": field.model_id.name
  29. }
  30. def dict_for_model(model):
  31. return {
  32. "id": model.id,
  33. "name": model.name,
  34. "model": model.model
  35. }
  36. class IrModel(models.Model):
  37. _inherit = 'ir.model'
  38. def _filter_bi_fields(self, ir_model_field_obj):
  39. name = ir_model_field_obj.name
  40. model = ir_model_field_obj.model_id
  41. model_name = model.model
  42. if name in self.env[model_name]._columns:
  43. f = self.env[model_name]._columns[name]
  44. return f._classic_write
  45. return False
  46. @api.model
  47. def _filter_bi_models(self, model):
  48. model_name = model["model"]
  49. if model_name in NO_BI_MODELS or \
  50. model_name.startswith("workflow") or \
  51. model_name.startswith("ir.") or \
  52. model["name"] == "Unknow" or \
  53. "report" in model_name or \
  54. model_name.startswith("base_") or \
  55. "_" in model_name or \
  56. "." in model["name"] or \
  57. "mail" in model_name or \
  58. "edi." in model_name:
  59. return False
  60. return self.env['ir.model.access'].check(
  61. model["model"], 'read', False)
  62. @api.model
  63. def get_related_fields(self, model_ids):
  64. """ Return list of field dicts for all fields that can be
  65. joined with models in model_ids
  66. """
  67. model_names = dict([(model.id, model.model)
  68. for model in self.env['ir.model'].sudo().search(
  69. [('id', 'in', model_ids.values())])])
  70. filter_bi_fields = self._filter_bi_fields
  71. if filter_bi_fields:
  72. rfields = [
  73. dict(dict_for_field(field),
  74. join_node=-1,
  75. table_alias=model[0])
  76. for field in filter(
  77. filter_bi_fields,
  78. self.env['ir.model.fields'].sudo().search(
  79. [('model_id', 'in', model_ids.values()),
  80. ('ttype', 'in', ['many2one'])]))
  81. for model in model_ids.items()
  82. if model[1] == field.model_id.id
  83. ]
  84. lfields = [
  85. dict(dict_for_field(field),
  86. join_node=model[0],
  87. table_alias=-1)
  88. for field in filter(
  89. filter_bi_fields,
  90. self.env['ir.model.fields'].sudo().search(
  91. [('relation', 'in', model_names.values()),
  92. ('ttype', 'in', ['many2one'])]))
  93. for model in model_ids.items()
  94. if model_names[model[1]] == field['relation']
  95. ]
  96. return [dict(field, join_node=model[0])
  97. for field in lfields
  98. if model_names[model[1]] == field['relation']] + [
  99. dict(field, table_alias=model[0])
  100. for model in model_ids.items()
  101. for field in rfields if model[1] == field['model_id']]
  102. @api.model
  103. def get_related_models(self, model_ids):
  104. """ Return list of model dicts for all models that can be
  105. joined with models in model_ids
  106. """
  107. related_fields = self.get_related_fields(model_ids)
  108. return sorted(filter(
  109. self._filter_bi_models,
  110. [{"id": model.id, "name": model.name, "model": model.model}
  111. for model in self.env['ir.model'].sudo().search(
  112. ['|',
  113. ('id', 'in', model_ids.values() + [
  114. f['model_id']
  115. for f in related_fields if f['table_alias'] == -1]),
  116. ('model', 'in', [
  117. f['relation']
  118. for f in related_fields if f['join_node'] == -1])])]),
  119. key=lambda x: x['name'])
  120. @api.model
  121. def get_models(self):
  122. """ Return list of model dicts for all available models.
  123. """
  124. models_domain = [('osv_memory', '=', False)]
  125. return sorted(filter(
  126. self._filter_bi_models,
  127. [dict_for_model(model)
  128. for model in self.search(models_domain)]),
  129. key=lambda x: x['name'])
  130. @api.model
  131. def get_join_nodes(self, field_data, new_field):
  132. """ Return list of field dicts of join nodes
  133. Return all possible join nodes to add new_field to the query
  134. containing model_ids.
  135. """
  136. model_ids = dict([(field['table_alias'],
  137. field['model_id']) for field in field_data])
  138. keys = [(field['table_alias'], field['id'])
  139. for field in field_data if field.get('join_node', -1) != -1]
  140. join_nodes = ([{'table_alias': alias}
  141. for alias, model_id in model_ids.items()
  142. if model_id == new_field['model_id']] + [
  143. d for d in self.get_related_fields(model_ids)
  144. if (d['relation'] == new_field['model'] and
  145. d['join_node'] == -1) or
  146. (d['model_id'] == new_field['model_id'] and
  147. d['table_alias'] == -1)])
  148. return filter(
  149. lambda x: 'id' not in x or
  150. (x['table_alias'], x['id']) not in keys, join_nodes)
  151. @api.model
  152. def get_fields(self, model_id):
  153. bi_field_domain = [
  154. ('model_id', '=', model_id),
  155. ("name", "not in", NO_BI_FIELDS),
  156. ('ttype', 'not in', [
  157. 'many2many', "one2many", "html", "binary", "reference"])
  158. ]
  159. filter_bi_fields = self._filter_bi_fields
  160. fields_obj = self.env['ir.model.fields']
  161. fields = filter(filter_bi_fields,
  162. fields_obj.sudo().search(bi_field_domain))
  163. return sorted([{"id": field.id,
  164. "model_id": model_id,
  165. "name": field.name,
  166. "description": field.field_description,
  167. "type": field.ttype,
  168. "custom": False,
  169. "model": field.model_id.model,
  170. "model_name": field.model_id.name}
  171. for field in fields], key=lambda x: x['description'],
  172. reverse=True)
  173. def create(self, cr, user, vals, context=None):
  174. if context is None:
  175. context = {}
  176. if context and context.get('bve'):
  177. vals['state'] = 'base'
  178. res = super(IrModel, self).create(cr, user, vals, context)
  179. if vals.get('state', 'base') == 'bve':
  180. vals['state'] = 'manual'
  181. # add model in registry
  182. self.instanciate(cr, user, vals['model'], context)
  183. self.pool.setup_models(cr, partial=(not self.pool.ready))
  184. # update database schema
  185. # model = self.pool[vals['model']]
  186. # ctx = dict(
  187. # context,
  188. # field_name=vals['name'],
  189. # field_state='manual',
  190. # select=vals.get('select_level', '0'),
  191. # update_custom_fields=True)
  192. RegistryManager.signal_registry_change(cr.dbname)
  193. self.write(cr, user, [res], {'state': 'manual'})
  194. return res