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.

136 lines
5.0 KiB

  1. # Copyright 2017 Therp BV <http://therp.nl>
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  3. # pylint: disable=consider-merging-classes-inherited
  4. from odoo import api, models, fields
  5. REASON_DUPLICATE = 1
  6. REASON_DEFAULT = 2
  7. REASON_DEFAULT_FALSE = 3
  8. REASON_UNKNOWN_MODEL = 4
  9. class CleanupPurgeLineProperty(models.TransientModel):
  10. _inherit = 'cleanup.purge.line'
  11. _name = 'cleanup.purge.line.property'
  12. _description = 'Purge properties'
  13. wizard_id = fields.Many2one(
  14. 'cleanup.purge.wizard.property', 'Purge Wizard', readonly=True)
  15. property_id = fields.Many2one('ir.property')
  16. reason = fields.Selection([
  17. (REASON_DUPLICATE, 'Duplicated property'),
  18. (REASON_DEFAULT, 'Same value as default'),
  19. (REASON_DEFAULT_FALSE, 'Empty default property'),
  20. (REASON_UNKNOWN_MODEL, 'Unknown model'),
  21. ])
  22. @api.multi
  23. def purge(self):
  24. """Delete properties"""
  25. self.write({'purged': True})
  26. return self.mapped('property_id').unlink()
  27. class CleanupPurgeWizardProperty(models.TransientModel):
  28. _inherit = 'cleanup.purge.wizard'
  29. _name = 'cleanup.purge.wizard.property'
  30. _description = 'Purge properties'
  31. @api.model
  32. def find(self):
  33. """
  34. Search property records which are duplicated or the same as the default
  35. """
  36. result = []
  37. default_properties = self.env['ir.property'].search([
  38. ('res_id', '=', False),
  39. ])
  40. handled_field_ids = []
  41. for prop in default_properties:
  42. value = None
  43. try:
  44. value = prop.get_by_record()
  45. except KeyError:
  46. result.append({
  47. 'name': '%s@%s: %s' % (
  48. prop.name, prop.res_id, value,
  49. ),
  50. 'property_id': prop.id,
  51. 'reason': REASON_UNKNOWN_MODEL,
  52. })
  53. continue
  54. if not value:
  55. result.append({
  56. 'name': '%s@%s: %s' % (
  57. prop.name, prop.res_id, value,
  58. ),
  59. 'property_id': prop.id,
  60. 'reason': REASON_DEFAULT_FALSE,
  61. })
  62. continue
  63. if prop.fields_id.id in handled_field_ids:
  64. continue
  65. domain = [
  66. ('id', '!=', prop.id),
  67. ('fields_id', '=', prop.fields_id.id),
  68. # =? explicitly tests for None or False, not falsyness
  69. ('value_float', '=?', prop.value_float or False),
  70. ('value_integer', '=?', prop.value_integer or False),
  71. ('value_text', '=?', prop.value_text or False),
  72. ('value_binary', '=?', prop.value_binary or False),
  73. ('value_reference', '=?', prop.value_reference or False),
  74. ('value_datetime', '=?', prop.value_datetime or False),
  75. ]
  76. if prop.company_id:
  77. domain.append(('company_id', '=', prop.company_id.id))
  78. else:
  79. domain.extend([
  80. '|',
  81. ('company_id', '=', False),
  82. (
  83. 'company_id', 'in', self.env['res.company'].search([
  84. (
  85. 'id', 'not in', default_properties.filtered(
  86. lambda x: x.company_id and
  87. x.fields_id == prop.fields_id
  88. ).ids,
  89. )
  90. ]).ids
  91. ),
  92. ])
  93. for redundant_property in self.env['ir.property'].search(domain):
  94. result.append({
  95. 'name': '%s@%s: %s' % (
  96. prop.name, redundant_property.res_id,
  97. prop.get_by_record()
  98. ),
  99. 'property_id': redundant_property.id,
  100. 'reason': REASON_DEFAULT,
  101. })
  102. handled_field_ids.append(prop.fields_id.id)
  103. self.env.cr.execute(
  104. '''
  105. with grouped_properties(ids, cnt) as (
  106. select array_agg(id), count(*)
  107. from ir_property group by res_id, company_id, fields_id
  108. )
  109. select ids from grouped_properties where cnt > 1
  110. '''
  111. )
  112. for ids, in self.env.cr.fetchall():
  113. # odoo uses the first property found by search
  114. for prop in self.env['ir.property'].search([
  115. ('id', 'in', ids)
  116. ])[1:]:
  117. result.append({
  118. 'name': '%s@%s: %s' % (
  119. prop.name, prop.res_id, prop.get_by_record()
  120. ),
  121. 'property_id': prop.id,
  122. 'reason': REASON_DUPLICATE,
  123. })
  124. return result
  125. purge_line_ids = fields.One2many(
  126. 'cleanup.purge.line.property', 'wizard_id', 'Properties to purge')