# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from trytond.model import ( MatchMixin, ModelSQL, ModelView, fields, sequence_ordered) from trytond.modules.product import ProductDeactivatableMixin from trytond.pool import Pool, PoolMeta from trytond.pyson import Bool, Eval, If from trytond.tools import is_full_text, lstrip_wildcard class ProductCustomer( sequence_ordered(), ProductDeactivatableMixin, MatchMixin, ModelSQL, ModelView): __name__ = 'sale.product_customer' template = fields.Many2One( 'product.template', "Product", required=True, ondelete='CASCADE', domain=[ If(Bool(Eval('product')), ('products', '=', Eval('product')), ()), ], states={ 'readonly': Eval('id', -1) >= 0, }) product = fields.Many2One( 'product.product', "Variant", domain=[ If(Bool(Eval('template')), ('template', '=', Eval('template')), ()), ], states={ 'readonly': Eval('id', -1) >= 0, }) party = fields.Many2One( 'party.party', "Customer", required=True, ondelete='CASCADE', states={ 'readonly': Eval('id', -1) >= 0, }) name = fields.Char("Name", translate=True) code = fields.Char("Code") @fields.depends( 'product', '_parent_product.template') def on_change_product(self): if self.product: self.template = self.product.template def get_rec_name(self, name): if not self.name and not self.code: if self.product: name = self.product.rec_name else: name = self.template.rec_name else: if self.name: name = self.name elif self.product: name = self.product.name else: name = self.template.name if self.code: name = '[' + self.code + '] ' + name return name @classmethod def search_rec_name(cls, name, clause): _, operator, operand, *extra = clause if operator.startswith('!') or operator.startswith('not '): bool_op = 'AND' else: bool_op = 'OR' code_value = operand if operator.endswith('like') and is_full_text(operand): code_value = lstrip_wildcard(operand) return [bool_op, ('template', operator, operand, *extra), ('product', operator, operand, *extra), ('party', operator, operand, *extra), ('code', operator, code_value, *extra), ('name', operator, operand, *extra), ] class Template(metaclass=PoolMeta): __name__ = 'product.template' product_customers = fields.One2Many( 'sale.product_customer', 'template', "Customers", states={ 'invisible': ~Eval('salable', False), }) def product_customer_used(self, **pattern): for product_customer in self.product_customers: if product_customer.match(pattern): yield product_customer @classmethod def copy(cls, templates, default=None): pool = Pool() ProductCustomer = pool.get('sale.product_customer') if default is None: default = {} else: default = default.copy() copy_customers = 'product_customers' not in default default.setdefault('product_customers', None) new_templates = super().copy(templates, default) if copy_customers: old2new = {} to_copy = [] for template, new_template in zip(templates, new_templates): to_copy.extend( pc for pc in template.product_customers if not pc.product) old2new[template.id] = new_template.id if to_copy: ProductCustomer.copy(to_copy, { 'template': lambda d: old2new[d['template']], }) return new_templates class Product(metaclass=PoolMeta): __name__ = 'product.product' product_customers = fields.One2Many( 'sale.product_customer', 'product', "Customers", domain=[ ('template', '=', Eval('template', -1)), ], states={ 'invisible': ~Eval('salable', False), }) def product_customer_used(self, **pattern): for product_customer in self.product_customers: if product_customer.match(pattern): yield product_customer pattern['product'] = None yield from self.template.product_customer_used(**pattern) @classmethod def copy(cls, products, default=None): pool = Pool() ProductCustomer = pool.get('sale.product_customer') if default is None: default = {} else: default = default.copy() copy_customers = 'product_customers' not in default if 'template' in default: default.setdefault('product_customers', None) new_products = super().copy(products, default) if 'template' in default and copy_customers: template2new = {} product2new = {} to_copy = [] for product, new_product in zip(products, new_products): if product.product_customers: to_copy.extend(product.product_customers) template2new[product.template.id] = new_product.template.id product2new[product.id] = new_product.id if to_copy: ProductCustomer.copy(to_copy, { 'product': lambda d: product2new[d['product']], 'template': lambda d: template2new[d['template']], }) return new_products