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.

218 lines
7.5 KiB

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