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.

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