Files
enterprise-addons/documents_product/models/document.py
T

102 lines
4.6 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.fields import Domain
class DocumentsDocument(models.Model):
_inherit = 'documents.document'
product_template_id = fields.Many2one('product.template', string="Product", compute='_compute_product', search='_search_product_template_id')
product_id = fields.Many2one('product.product', string="Product Variant", compute='_compute_product', search='_search_product_id')
@api.depends('res_id', 'res_model')
def _compute_product(self):
ProductTemplate = self.env['product.template']
Product = self.env['product.product']
for document in self:
document.product_template_id = document.res_model == 'product.template' and ProductTemplate.browse(document.res_id)
document.product_id = document.res_model == 'product.product' and Product.browse(document.res_id)
@api.model
def _search_product_template_id(self, operator, value):
return self._search_related_product_field(operator, value, 'product_template_id')
@api.model
def _search_product_id(self, operator, value):
return self._search_related_product_field(operator, value, 'product_id')
@api.model
def _search_related_product_field(self, operator, value, field_name) -> Domain:
assert field_name in ('product_template_id', 'product_id')
Model = self.env[self._fields[field_name].comodel_name]
if operator == 'in':
if True in value:
# support for True value
return Domain(field_name, 'not in', [False]) | Domain(field_name, 'in', value - {True})
if False in value:
return Domain('res_model', '!=', Model._name) | self._search_related_product_field(operator, value - {False}, field_name)
query_model = Model._search(Domain.OR(
Domain(Model._rec_name if isinstance(v, str) else 'id', operator, v)
for v in value
if v
))
elif operator == 'any' and isinstance(value, Domain):
query_model = Model._search(value)
elif operator.endswith('like') and not operator.startswith('not'):
query_model = Model._search([(Model._rec_name, operator, value)])
else:
return NotImplemented
return (Domain.FALSE if query_model.is_empty() else Domain('res_id', 'in', query_model)) & Domain('res_model', '=', Model._name)
def create_product_template(self):
# JUC: WTF? A single product for many documents, and the created
# product has the image of the first document?!
product = self.env['product.template'].create({
'name': _('Product created from Documents')
})
for document in self:
if document.res_model or document.res_id:
att_copy = document.attachment_id.with_context(no_document=True).copy()
document = document.copy({'attachment_id': att_copy.id})
document.write({
'res_model': product._name,
'res_id': product.id,
})
is_image = (document.mimetype or '').partition('/')[0] == 'image'
if is_image and not product.image_1920:
product.write({'image_1920': document.datas})
view_id = product.get_formview_id()
return {
'type': 'ir.actions.act_window',
'res_model': 'product.template',
'name': "New product template",
'context': self.env.context,
'view_mode': 'form',
'views': [(view_id, "form")],
'res_id': product.id,
'view_id': view_id,
}
def write(self, vals):
"""Sync product.document attachment when a document sharing a common
attachment with a product/template is updated."""
documents_for_products = self.filtered(
lambda d: d.res_model in ('product.template', 'product.product')
and d.attachment_id
)
if 'attachment_id' not in vals or not documents_for_products:
return super().write(vals)
document_by_old_attachment = documents_for_products.grouped('attachment_id')
res = super().write(vals)
product_docs = self.env['product.document'].search([
('ir_attachment_id', 'in', [a.id for a in document_by_old_attachment])
])
for product_doc in product_docs:
updated_related_document = document_by_old_attachment[product_doc.ir_attachment_id]
product_doc.ir_attachment_id = updated_related_document.attachment_id
return res