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.5 KiB

  1. # Copyright 2018 Akretion - Benoît Guillot
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. import hashlib
  4. from collections import OrderedDict
  5. from odoo import _, exceptions, fields, models
  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. def write(self, vals):
  71. version_fields = self._version_fields()
  72. has_written_versioned_fields = any((f in version_fields) for f in vals.keys())
  73. for partner in self:
  74. if (
  75. not partner.version_hash
  76. and not vals.get("version_hash", False)
  77. and has_written_versioned_fields
  78. ):
  79. partner._version_apply()
  80. if partner.version_hash and has_written_versioned_fields:
  81. raise exceptions.UserError(
  82. _(
  83. "You can't modify a versioned field %s on the "
  84. "versioned partner %s."
  85. )
  86. % (version_fields, partner.name)
  87. )
  88. return super(ResPartner, self).write(vals)
  89. def _version_create(self):
  90. version_hash = self._version_hash()
  91. default = {
  92. "active": False,
  93. "version_hash": version_hash,
  94. "parent_id": self.parent_id.id if self.parent_id else self.id,
  95. "date_version": fields.Datetime.now(),
  96. }
  97. return self.copy(default=default)