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.

172 lines
5.9 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # © 2004-2010 Tiny SPRL http://tiny.be
  4. # © 2010-2012 ChriCar Beteiligungs- und Beratungs- GmbH
  5. # http://www.camptocamp.at
  6. # © 2015 Antiun Ingenieria, SL (Madrid, Spain)
  7. # http://www.antiun.com
  8. # Antonio Espinosa <antonioea@antiun.com>
  9. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  10. from odoo import api, models, fields, _
  11. from odoo.exceptions import ValidationError
  12. class ResPartner(models.Model):
  13. _inherit = 'res.partner'
  14. id_numbers = fields.One2many(
  15. comodel_name='res.partner.id_number',
  16. inverse_name='partner_id',
  17. string="Identification Numbers",
  18. )
  19. @api.multi
  20. @api.depends('id_numbers')
  21. def _compute_identification(self, field_name, category_code):
  22. """ Compute a field that indicates a certain ID type.
  23. Use this on a field that represents a certain ID type. It will compute
  24. the desired field as that ID(s).
  25. This ID can be worked with as if it were a Char field, but it will
  26. be relating back to a ``res.partner.id_number`` instead.
  27. Example:
  28. .. code-block:: python
  29. social_security = fields.Char(
  30. compute=lambda s: s._compute_identification(
  31. 'social_security', 'SSN',
  32. ),
  33. inverse=lambda s: s._inverse_identification(
  34. 'social_security', 'SSN',
  35. ),
  36. search=lambda s, *a: s._search_identification(
  37. 'SSN', *a
  38. ),
  39. )
  40. Args:
  41. field_name (str): Name of field to set.
  42. category_code (str): Category code of the Identification type.
  43. """
  44. for record in self:
  45. id_numbers = record.id_numbers.filtered(
  46. lambda r: r.category_id.code == category_code
  47. )
  48. if not id_numbers:
  49. continue
  50. value = id_numbers[0].name
  51. record[field_name] = value
  52. @api.multi
  53. def _inverse_identification(self, field_name, category_code):
  54. """ Inverse for an identification field.
  55. This method will create a new record, or modify the existing one
  56. in order to allow for the associated field to work like a Char.
  57. If a category does not exist of the correct code, it will be created
  58. using `category_code` as both the `name` and `code` values.
  59. If the value of the target field is unset, the associated ID will
  60. be deactivated in order to preserve history.
  61. Example:
  62. .. code-block:: python
  63. social_security = fields.Char(
  64. compute=lambda s: s._compute_identification(
  65. 'social_security', 'SSN',
  66. ),
  67. inverse=lambda s: s._inverse_identification(
  68. 'social_security', 'SSN',
  69. ),
  70. search=lambda s, *a: s._search_identification(
  71. 'SSN', *a
  72. ),
  73. )
  74. Args:
  75. field_name (str): Name of field to set.
  76. category_code (str): Category code of the Identification type.
  77. """
  78. for record in self:
  79. id_number = record.id_numbers.filtered(
  80. lambda r: r.category_id.code == category_code
  81. )
  82. record_len = len(id_number)
  83. # Record for category is not existent.
  84. if record_len == 0:
  85. name = record[field_name]
  86. if not name:
  87. # No value to set
  88. continue
  89. category = self.env['res.partner.id_category'].search([
  90. ('code', '=', category_code),
  91. ])
  92. if not category:
  93. category = self.env['res.partner.id_category'].create({
  94. 'code': category_code,
  95. 'name': category_code,
  96. })
  97. self.env['res.partner.id_number'].create({
  98. 'partner_id': record.id,
  99. 'category_id': category.id,
  100. 'name': name,
  101. })
  102. # There was an identification record singleton found.
  103. elif record_len == 1:
  104. value = record[field_name]
  105. if value:
  106. id_number.name = value
  107. else:
  108. id_number.active = False
  109. # Guard against writing wrong records.
  110. else:
  111. raise ValidationError(_(
  112. 'This %s has multiple IDs of this type (%s), so a write '
  113. 'via the %s field is not possible. In order to fix this, '
  114. 'please use the IDs tab.',
  115. ) % (
  116. record._name, category_code, field_name,
  117. ))
  118. @api.model
  119. def _search_identification(self, category_code, operator, value):
  120. """ Search method for an identification field.
  121. Example:
  122. .. code-block:: python
  123. social_security = fields.Char(
  124. compute=lambda s: s._compute_identification(
  125. 'social_security', 'SSN',
  126. ),
  127. inverse=lambda s: s._inverse_identification(
  128. 'social_security', 'SSN',
  129. ),
  130. search=lambda s, *a: s._search_identification(
  131. 'SSN', *a
  132. ),
  133. )
  134. Args:
  135. category_code (str): Category code of the Identification type.
  136. operator (str): Operator of domain.
  137. value (str): Value to search for.
  138. Returns:
  139. list: Domain to search with.
  140. """
  141. id_numbers = self.env['res.partner.id_number'].search([
  142. ('name', operator, value),
  143. ('category_id.code', '=', category_code),
  144. ])
  145. return [
  146. ('id_numbers.id', 'in', id_numbers.ids),
  147. ]