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.

217 lines
7.5 KiB

  1. # Copyright 2015 Antiun Ingeniería S.L. - Antonio Espinosa
  2. # Copyright 2015-2016 Jairo Llopis <jairo.llopis@tecnativa.com>
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from odoo import _, models, fields, api, exceptions
  5. class IrExportsLine(models.Model):
  6. _inherit = 'ir.exports.line'
  7. _order = 'sequence,id'
  8. name = fields.Char(
  9. required=False,
  10. readonly=True,
  11. store=True,
  12. compute="_compute_name",
  13. inverse="_inverse_name",
  14. help="Field's technical name.")
  15. field1_id = fields.Many2one(
  16. "ir.model.fields",
  17. "First field",
  18. domain="[('model_id', '=', model1_id)]")
  19. field2_id = fields.Many2one(
  20. "ir.model.fields",
  21. "Second field",
  22. domain="[('model_id', '=', model2_id)]")
  23. field3_id = fields.Many2one(
  24. "ir.model.fields",
  25. "Third field",
  26. domain="[('model_id', '=', model3_id)]")
  27. field4_id = fields.Many2one(
  28. "ir.model.fields",
  29. "Fourth field",
  30. domain="[('model_id', '=', model4_id)]")
  31. model1_id = fields.Many2one(
  32. "ir.model",
  33. "First model",
  34. readonly=True,
  35. default=lambda self: self._default_model1_id(),
  36. related="export_id.model_id")
  37. model2_id = fields.Many2one(
  38. "ir.model",
  39. "Second model",
  40. compute="_compute_model2_id")
  41. model3_id = fields.Many2one(
  42. "ir.model",
  43. "Third model",
  44. compute="_compute_model3_id")
  45. model4_id = fields.Many2one(
  46. "ir.model",
  47. "Fourth model",
  48. compute="_compute_model4_id")
  49. sequence = fields.Integer()
  50. label = fields.Char(
  51. compute="_compute_label")
  52. @api.model
  53. def _default_model1_id(self):
  54. """Default model depending on context."""
  55. return self.env.context.get("default_model1_id", False)
  56. @api.multi
  57. @api.depends("field1_id", "field2_id", "field3_id", "field4_id")
  58. def _compute_name(self):
  59. """Get the name from the selected fields."""
  60. for one in self:
  61. name = "/".join((one.field_n(num).name for num in range(1, 5)
  62. if one.field_n(num)))
  63. if name != one.name:
  64. one.name = name
  65. @api.multi
  66. @api.depends("field1_id")
  67. def _compute_model2_id(self):
  68. """Get the related model for the second field."""
  69. IrModel = self.env["ir.model"]
  70. for one in self:
  71. one.model2_id = (
  72. one.field1_id.ttype and
  73. "2" in one.field1_id.ttype and
  74. IrModel.search([("model", "=", one.field1_id.relation)]))
  75. @api.multi
  76. @api.depends("field2_id")
  77. def _compute_model3_id(self):
  78. """Get the related model for the third field."""
  79. IrModel = self.env["ir.model"]
  80. for one in self:
  81. one.model3_id = (
  82. one.field2_id.ttype and
  83. "2" in one.field2_id.ttype and
  84. IrModel.search([("model", "=", one.field2_id.relation)]))
  85. @api.multi
  86. @api.depends("field3_id")
  87. def _compute_model4_id(self):
  88. """Get the related model for the third field."""
  89. IrModel = self.env["ir.model"]
  90. for one in self:
  91. one.model4_id = (
  92. one.field3_id.ttype and
  93. "2" in one.field3_id.ttype and
  94. IrModel.search([("model", "=", one.field3_id.relation)]))
  95. @api.multi
  96. @api.depends('name')
  97. def _compute_label(self):
  98. """Column label in a user-friendly format and language."""
  99. for one in self:
  100. parts = list()
  101. for num in range(1, 5):
  102. field = one.field_n(num)
  103. if not field:
  104. break
  105. # Translate label if possible
  106. try:
  107. parts.append(
  108. one.env[one.model_n(num).model]._fields[field.name]
  109. .get_description(one.env)["string"])
  110. except KeyError:
  111. # No human-readable string available, so empty this
  112. return
  113. one.label = ("%s (%s)" % ("/".join(parts), one.name)
  114. if parts and one.name else False)
  115. @api.multi
  116. def _inverse_name(self):
  117. """Get the fields from the name."""
  118. for one in self:
  119. # Field names can have up to only 4 indentation levels
  120. parts = one.name.split("/")
  121. if len(parts) > 4:
  122. raise exceptions.ValidationError(
  123. _("It's not allowed to have more than 4 levels depth: "
  124. "%s") % one.name)
  125. for num in range(1, 5):
  126. if num > len(parts):
  127. # Empty subfield in this case
  128. one[one.field_n(num, True)] = False
  129. continue
  130. field_name = parts[num - 1]
  131. model = one.model_n(num)
  132. # You could get to failing constraint while populating the
  133. # fields, so we skip the uniqueness check and manually check
  134. # the full constraint after the loop
  135. one.with_context(skip_check=True)[one.field_n(num, True)] = (
  136. one._get_field_id(model, field_name))
  137. one._check_name()
  138. @api.multi
  139. @api.constrains("field1_id", "field2_id", "field3_id", "field4_id")
  140. def _check_name(self):
  141. for one in self:
  142. if not one.label:
  143. raise exceptions.ValidationError(
  144. _("Field '%s' does not exist") % one.name)
  145. if not one.env.context.get('skip_check'):
  146. lines = one.search([('export_id', '=', one.export_id.id),
  147. ('name', '=', one.name)])
  148. if len(lines) > 1:
  149. raise exceptions.ValidationError(
  150. _("Field '%s' already exists") % one.name)
  151. @api.multi
  152. @api.onchange('name')
  153. def _onchange_name(self):
  154. if self.name:
  155. self._inverse_name()
  156. else:
  157. self.field1_id = False
  158. self.field2_id = False
  159. self.field3_id = False
  160. self.field4_id = False
  161. @api.model
  162. def _get_field_id(self, model, name):
  163. """Get a field object from its model and name.
  164. :param int model:
  165. ``ir.model`` object that contains the field.
  166. :param str name:
  167. Technical name of the field, like ``child_ids``.
  168. """
  169. field = self.env["ir.model.fields"].search(
  170. [("name", "=", name),
  171. ("model_id", "=", model.id)])
  172. if not field.exists():
  173. raise exceptions.ValidationError(
  174. _("Field '%s' not found in model '%s'") % (name, model.model))
  175. return field
  176. @api.multi
  177. def field_n(self, n, only_name=False):
  178. """Helper to choose the field according to its indentation level.
  179. :param int n:
  180. Number of the indentation level to choose the field, from 1 to 3.
  181. :param bool only_name:
  182. Return only the field name, or return its value.
  183. """
  184. name = "field%d_id" % n
  185. return name if only_name else self[name]
  186. @api.multi
  187. def model_n(self, n, only_name=False):
  188. """Helper to choose the model according to its indentation level.
  189. :param int n:
  190. Number of the indentation level to choose the model, from 1 to 3.
  191. :param bool only_name:
  192. Return only the model name, or return its value.
  193. """
  194. name = "model%d_id" % n
  195. return name if only_name else self[name]