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.

113 lines
3.6 KiB

  1. # Copyright 2018 Akretion - Benoît Guillot
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. from odoo import fields, models, api, exceptions, _
  4. import hashlib
  5. from collections import OrderedDict
  6. class ResPartner(models.Model):
  7. _inherit = "res.partner"
  8. version_hash = fields.Char(readonly=True, copy=False)
  9. date_version = fields.Datetime(string="Date version", readonly=True)
  10. def get_version_fields(self):
  11. # deprecated uses _version_fields instead
  12. return self._version_fields()
  13. def _version_fields(self):
  14. return [
  15. "name",
  16. "street",
  17. "street2",
  18. "zip",
  19. "city",
  20. "country_id",
  21. "parent_id",
  22. ]
  23. def get_version_hash(self):
  24. # deprecated uses _version_hash instead
  25. return self._version_hash()
  26. def _version_hash(self):
  27. version_fields = self._version_fields()
  28. version = OrderedDict()
  29. for field in version_fields:
  30. if field == "parent_id":
  31. parent_id = self.parent_id.id if self.parent_id else self.id
  32. version[field] = parent_id
  33. elif self[field]:
  34. version[field] = self[field]
  35. version_hash = hashlib.md5(str(version).encode("utf-8")).hexdigest()
  36. return version_hash
  37. def _version_impacted_tables(self):
  38. """
  39. :return:
  40. - list of tables to update in case of address versioning
  41. """
  42. return []
  43. def _version_exclude_keys(self):
  44. """
  45. :return:
  46. - dict:
  47. key = table name
  48. value = list of columns to ignore in case of address
  49. versioning
  50. """
  51. return {}
  52. def _version_need(self):
  53. """
  54. This method is supposed to be overriden to determine when
  55. an address versioning is needed or not
  56. :return: True if versioning is required else False
  57. """
  58. return False
  59. def _version_apply(self):
  60. self.ensure_one()
  61. if self._version_need():
  62. # the address is used, create a new version and
  63. # update related tables
  64. version_p = self._version_create()
  65. partner_wizard = self.env[
  66. "base.partner.merge.automatic.wizard"
  67. ].with_context(address_version=True)
  68. partner_wizard._update_foreign_keys(self, version_p)
  69. return False
  70. @api.multi
  71. def write(self, vals):
  72. version_fields = self._version_fields()
  73. has_written_versioned_fields = any((f in version_fields) for f in vals.keys())
  74. for partner in self:
  75. if (
  76. not partner.version_hash
  77. and not vals.get("version_hash", False)
  78. and has_written_versioned_fields
  79. ):
  80. partner._version_apply()
  81. if partner.version_hash and has_written_versioned_fields:
  82. raise exceptions.UserError(
  83. _(
  84. "You can't modify a versioned field %s on the "
  85. "versioned partner %s."
  86. )
  87. % (version_fields, partner.name)
  88. )
  89. return super(ResPartner, self).write(vals)
  90. def _version_create(self):
  91. version_hash = self._version_hash()
  92. default = {
  93. "active": False,
  94. "version_hash": version_hash,
  95. "parent_id": self.parent_id.id if self.parent_id else self.id,
  96. "date_version": fields.Datetime.now(),
  97. }
  98. return self.copy(default=default)