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.

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