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.

193 lines
6.4 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2015 Antiun Ingeniería S.L. - Antonio Espinosa
  3. # Copyright 2015-2016 Jairo Llopis <jairo.llopis@tecnativa.com>
  4. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  5. from openerp import models, fields, api, exceptions
  6. from openerp.tools.translate import _
  7. class IrExportsLine(models.Model):
  8. _inherit = 'ir.exports.line'
  9. _order = 'sequence,id'
  10. name = fields.Char(
  11. required=False,
  12. readonly=True,
  13. store=True,
  14. compute="_compute_name",
  15. inverse="_inverse_name",
  16. help="Field's technical name.")
  17. field1_id = fields.Many2one(
  18. "ir.model.fields",
  19. "First field",
  20. domain="[('model_id', '=', model1_id)]")
  21. field2_id = fields.Many2one(
  22. "ir.model.fields",
  23. "Second field",
  24. domain="[('model_id', '=', model2_id)]")
  25. field3_id = fields.Many2one(
  26. "ir.model.fields",
  27. "Third field",
  28. domain="[('model_id', '=', model3_id)]")
  29. model1_id = fields.Many2one(
  30. "ir.model",
  31. "First model",
  32. readonly=True,
  33. default=lambda self: self._default_model1_id(),
  34. related="export_id.model_id")
  35. model2_id = fields.Many2one(
  36. "ir.model",
  37. "Second model",
  38. compute="_compute_model2_id")
  39. model3_id = fields.Many2one(
  40. "ir.model",
  41. "Third model",
  42. compute="_compute_model3_id")
  43. sequence = fields.Integer()
  44. label = fields.Char(
  45. compute="_compute_label")
  46. @api.model
  47. def _default_model1_id(self):
  48. """Default model depending on context."""
  49. return self.env.context.get("default_model1_id", False)
  50. @api.multi
  51. @api.depends("field1_id", "field2_id", "field3_id")
  52. def _compute_name(self):
  53. """Get the name from the selected fields."""
  54. for s in self:
  55. s.name = "/".join((s.field_n(num).name
  56. for num in range(1, 4)
  57. if s.field_n(num)))
  58. @api.multi
  59. @api.depends("field1_id")
  60. def _compute_model2_id(self):
  61. """Get the related model for the second field."""
  62. ir_model = self.env["ir.model"]
  63. for s in self:
  64. s.model2_id = (
  65. s.field1_id.ttype and
  66. "2" in s.field1_id.ttype and
  67. ir_model.search([("model", "=", s.field1_id.relation)]))
  68. @api.multi
  69. @api.depends("field2_id")
  70. def _compute_model3_id(self):
  71. """Get the related model for the third field."""
  72. ir_model = self.env["ir.model"]
  73. for s in self:
  74. s.model3_id = (
  75. s.field2_id.ttype and
  76. "2" in s.field2_id.ttype and
  77. ir_model.search([("model", "=", s.field2_id.relation)]))
  78. @api.multi
  79. @api.depends('name')
  80. def _compute_label(self):
  81. """Column label in a user-friendly format and language."""
  82. translations = self.env["ir.translation"]
  83. for s in self:
  84. parts = list()
  85. for num in range(1, 4):
  86. field = s.field_n(num)
  87. if not field:
  88. break
  89. # Translate label if possible
  90. parts.append(
  91. translations.search([
  92. ("type", "=", "field"),
  93. ("lang", "=", self.env.context.get("lang")),
  94. ("name", "=", "%s,%s" % (s.model_n(num).model,
  95. field.name)),
  96. ]).value or
  97. field.display_name)
  98. s.label = ("%s (%s)" % ("/".join(parts), s.name)
  99. if parts and s.name else False)
  100. @api.multi
  101. def _inverse_name(self):
  102. """Get the fields from the name."""
  103. for s in self:
  104. # Field names can have up to only 3 indentation levels
  105. parts = s.name.split("/", 2)
  106. for num in range(1, 4):
  107. try:
  108. # Fail in excessive subfield level
  109. field_name = parts[num - 1]
  110. except IndexError:
  111. # Remove subfield on failure
  112. s[s.field_n(num, True)] = False
  113. else:
  114. model = s.model_n(num)
  115. s[s.field_n(num, True)] = self._get_field_id(
  116. model, field_name)
  117. @api.one
  118. @api.constrains("field1_id", "field2_id", "field3_id")
  119. def _check_name(self):
  120. if not self.label:
  121. raise exceptions.ValidationError(
  122. _("Field '%s' does not exist") % self.name)
  123. lines = self.search([('export_id', '=', self.export_id.id),
  124. ('name', '=', self.name)])
  125. if len(lines) > 1:
  126. raise exceptions.ValidationError(
  127. _("Field '%s' already exists") % self.name)
  128. @api.model
  129. def _install_base_export_manager(self):
  130. """Populate ``field*_id`` fields."""
  131. self.search([("export_id", "=", False)]).unlink()
  132. lines = self.search(
  133. [("field1_id", "=", False), ("name", "!=", False)])
  134. for line in lines:
  135. try:
  136. line._inverse_name()
  137. except:
  138. # Prevent possible inexisting fields
  139. pass
  140. @api.model
  141. def _get_field_id(self, model, name):
  142. """Get a field object from its model and name.
  143. :param int model:
  144. ``ir.model`` object that contains the field.
  145. :param str name:
  146. Technical name of the field, like ``child_ids``.
  147. """
  148. return self.env["ir.model.fields"].search(
  149. [("name", "=", name),
  150. ("model_id", "=", model.id)])
  151. @api.multi
  152. def field_n(self, n, only_name=False):
  153. """Helper to choose the field according to its indentation level.
  154. :param int n:
  155. Number of the indentation level to choose the field, from 1 to 3.
  156. :param bool only_name:
  157. Return only the field name, or return its value.
  158. """
  159. name = "field%d_id" % n
  160. return name if only_name else self[name]
  161. @api.multi
  162. def model_n(self, n, only_name=False):
  163. """Helper to choose the model according to its indentation level.
  164. :param int n:
  165. Number of the indentation level to choose the model, from 1 to 3.
  166. :param bool only_name:
  167. Return only the model name, or return its value.
  168. """
  169. name = "model%d_id" % n
  170. return name if only_name else self[name]