class BaseModuleUninstall(models.TransientModel): _name = "base.module.uninstall" _description = "Module Uninstall" show_all = fields.Boolean() module_id = fields.Many2one( 'ir.module.module', string="Module", required=True, domain=[('state', 'in', ['installed', 'to upgrade', 'to install'])], ondelete='cascade', readonly=True, ) module_ids = fields.Many2many('ir.module.module', string="Impacted modules", compute='_compute_module_ids') model_ids = fields.Many2many('ir.model', string="Impacted data models", compute='_compute_model_ids') def _get_modules(self): """ Return all the modules impacted by self. """ return self.module_id.downstream_dependencies(self.module_id) @api.depends('module_id', 'show_all') def _compute_module_ids(self): for wizard in self: modules = wizard._get_modules() wizard.module_ids = modules if wizard.show_all else modules.filtered( 'application') def _get_models(self): """ Return the models (ir.model) to consider for the impact. """ return self.env['ir.model'].search([('transient', '=', False)]) @api.depends('module_ids') def _compute_model_ids(self): ir_models = self._get_models() ir_models_xids = ir_models._get_external_ids() for wizard in self: if wizard.module_id: module_names = set(wizard._get_modules().mapped('name')) def lost(model): xids = ir_models_xids.get(model.id, ()) return xids and all( xid.split('.')[0] in module_names for xid in xids) # find the models that have all their XIDs in the given modules self.model_ids = ir_models.filtered(lost).sorted('name') @api.onchange('module_id') def _onchange_module_id(self): # if we select a technical module, show technical modules by default if not self.module_id.application: self.show_all = True def action_uninstall(self): modules = self.module_id return modules.button_immediate_uninstall()
class PurchaseOrderLine(models.Model): _inherit = "purchase.order.line" product_template_id = fields.Many2one('product.template', string='Product Template', related="product_id.product_tmpl_id", domain=[('purchase_ok', '=', True)]) is_configurable_product = fields.Boolean( 'Is the product configurable?', related="product_template_id.has_configurable_attributes") product_template_attribute_value_ids = fields.Many2many( related='product_id.product_template_attribute_value_ids', readonly=True) product_no_variant_attribute_value_ids = fields.Many2many( 'product.template.attribute.value', string='Product attribute values that do not create variants', ondelete='restrict') def _get_product_purchase_description(self, product): name = super(PurchaseOrderLine, self)._get_product_purchase_description(product) for no_variant_attribute_value in self.product_no_variant_attribute_value_ids: name += "\n" + no_variant_attribute_value.attribute_id.name + ': ' + no_variant_attribute_value.name return name
class ModelB(models.Model): _name = 'test_new_api.model_b' _description = 'Model B' name = fields.Char() a_restricted_a_ids = fields.Many2many('test_new_api.model_a', relation='rel_model_a_model_b_1', ondelete='restrict') b_restricted_a_ids = fields.Many2many('test_new_api.model_a', relation='rel_model_a_model_b_2')
class ProductPublicCategory(models.Model): _name = "product.public.category" _inherit = ["website.seo.metadata", "website.multi.mixin", 'image.mixin'] _description = "Website Product Category" _parent_store = True _order = "sequence, name" name = fields.Char(required=True, translate=True) parent_id = fields.Many2one('product.public.category', string='Parent Category', index=True) parent_path = fields.Char(index=True) child_id = fields.One2many('product.public.category', 'parent_id', string='Children Categories') parents_and_self = fields.Many2many('product.public.category', compute='_compute_parents_and_self') sequence = fields.Integer( help= "Gives the sequence order when displaying a list of product categories.", index=True) website_description = fields.Html('Category Description', sanitize_attributes=False, translate=html_translate) product_tmpl_ids = fields.Many2many( 'product.template', relation='product_public_category_product_template_rel') @api.constrains('parent_id') def check_parent_id(self): if not self._check_recursion(): raise ValueError( _('Error ! You cannot create recursive categories.')) def name_get(self): res = [] for category in self: res.append((category.id, " / ".join(category.parents_and_self.mapped('name')))) return res def unlink(self): self.child_id.parent_id = None return super(ProductPublicCategory, self).unlink() def _compute_parents_and_self(self): for category in self: if category.parent_path: category.parents_and_self = self.env[ 'product.public.category'].browse( [int(p) for p in category.parent_path.split('/')[:-1]]) else: category.parents_and_self = category
class TemplatePreview(models.TransientModel): _inherit = "mail.template" _name = "email_template.preview" _description = "Email Template Preview" @api.model def _get_records(self): """ Return Records of particular Email Template's Model """ template_id = self._context.get('template_id') default_res_id = self._context.get('default_res_id') if not template_id: return [] template = self.env['mail.template'].browse(int(template_id)) records = self.env[template.model_id.model].search([], order="id desc", limit=10) records |= records.browse(default_res_id) return records.name_get() @api.model def _get_languages(self): return self.env['res.lang'].get_installed() @api.model def default_get(self, fields): result = super(TemplatePreview, self).default_get(fields) template = self._context.get('template_id') and self.env['mail.template'].browse(self._context['template_id']) or False if 'res_id' in fields and not result.get('res_id'): records = self._get_records() result['res_id'] = records and records[0][0] or False # select first record as a Default if template and 'model_id' in fields and not result.get('model_id'): result['model_id'] = template.model_id.id if template and 'preview_lang' in fields and not result.get('preview_lang') and result.get('res_id'): result['preview_lang'] = template.lang and template.generate_email(result['res_id'], ['lang'])['lang'] or template._context.get('lang') return result res_id = fields.Selection(_get_records, 'Sample Document') partner_ids = fields.Many2many('res.partner', string='Recipients') attachment_ids = fields.Many2many(string='Attachments', store=False) preview_lang = fields.Selection(_get_languages, string='Template Preview Language') @api.onchange('res_id', 'preview_lang') def on_change_res_id(self): if not self.res_id: return {} mail_values = {} if self._context.get('template_id'): template = self.env['mail.template'].browse(self._context['template_id']) self.name = template.name mail_values = template.with_context(template_preview_lang=self.preview_lang).generate_email(self.res_id) for field in ['email_from', 'email_to', 'email_cc', 'reply_to', 'subject', 'body_html', 'partner_to', 'partner_ids', 'attachment_ids']: setattr(self, field, mail_values.get(field, False))
class SaleProductConfigurator(models.TransientModel): _name = 'sale.product.configurator' _description = 'Sale Product Configurator' product_template_id = fields.Many2one( 'product.template', string="Product", required=True, domain=[('sale_ok', '=', True), ('attribute_line_ids.value_ids', '!=', False)]) quantity = fields.Integer('Quantity') pricelist_id = fields.Many2one('product.pricelist', 'Pricelist', readonly=True) product_template_attribute_value_ids = fields.Many2many( 'product.template.attribute.value', 'product_configurator_template_attribute_value_rel', string='Attribute Values', readonly=True) product_custom_attribute_value_ids = fields.Many2many( 'product.attribute.custom.value', 'product_configurator_custom_attribute_value_rel', string="Custom Values") product_no_variant_attribute_value_ids = fields.Many2many( 'product.template.attribute.value', 'product_configurator_no_variant_attribute_value_rel', string="Extra Values")
class ResPartner(models.Model): _inherit = 'res.partner' slide_channel_ids = fields.Many2many( 'slide.channel', 'slide_channel_partner', 'partner_id', 'channel_id', string='eLearning Courses') slide_channel_count = fields.Integer('Course Count', compute='_compute_slide_channel_count') slide_channel_company_count = fields.Integer('Company Course Count', compute='_compute_slide_channel_company_count') @api.depends('is_company') def _compute_slide_channel_count(self): read_group_res = self.env['slide.channel.partner'].sudo().read_group( [('partner_id', 'in', self.ids)], ['partner_id'], 'partner_id' ) data = dict((res['partner_id'][0], res['partner_id_count']) for res in read_group_res) for partner in self: partner.slide_channel_count = data.get(partner.id, 0) @api.depends('is_company', 'child_ids.slide_channel_count') def _compute_slide_channel_company_count(self): for partner in self: if partner.is_company: partner.slide_channel_company_count = self.env['slide.channel'].sudo().search_count( [('partner_ids', 'in', partner.child_ids.ids)] ) else: partner.slide_channel_company_count = 0 def action_view_courses(self): action = self.env.ref('website_slides.slide_channel_action_overview').read()[0] action['name'] = _('Followed Courses') action['domain'] = ['|', ('partner_ids', 'in', self.ids), ('partner_ids', 'in', self.child_ids.ids)] return action
class WebsiteVisitor(models.Model): _inherit = 'website.visitor' visitor_product_count = fields.Integer('Product Views', compute="_compute_product_statistics", help="Total number of views on products") product_ids = fields.Many2many('product.product', string="Visited Products", compute="_compute_product_statistics") product_count = fields.Integer('Products Views', compute="_compute_product_statistics", help="Total number of product viewed") @api.depends('website_track_ids') def _compute_product_statistics(self): results = self.env['website.track'].read_group( [('visitor_id', 'in', self.ids), ('product_id', '!=', False)], ['visitor_id', 'product_id'], ['visitor_id', 'product_id'], lazy=False) mapped_data = {} for result in results: visitor_info = mapped_data.get(result['visitor_id'][0], {'product_count': 0, 'product_ids': set()}) visitor_info['product_count'] += result['__count'] visitor_info['product_ids'].add(result['product_id'][0]) mapped_data[result['visitor_id'][0]] = visitor_info for visitor in self: visitor_info = mapped_data.get(visitor.id, {'product_ids': [], 'product_count': 0}) visitor.product_ids = [(6, 0, visitor_info['product_ids'])] visitor.visitor_product_count = visitor_info['product_count'] visitor.product_count = len(visitor_info['product_ids']) def _add_viewed_product(self, product_id): """ add a website_track with a page marked as viewed""" self.ensure_one() if product_id and self.env['product.product'].browse(product_id)._is_variant_possible(): domain = [('product_id', '=', product_id)] website_track_values = {'product_id': product_id, 'visit_datetime': datetime.now()} self._add_tracking(domain, website_track_values)
class StockImmediateTransfer(models.TransientModel): _name = 'stock.immediate.transfer' _description = 'Immediate Transfer' pick_ids = fields.Many2many('stock.picking', 'stock_picking_transfer_rel') def process(self): pick_to_backorder = self.env['stock.picking'] pick_to_do = self.env['stock.picking'] for picking in self.pick_ids: # If still in draft => confirm and assign if picking.state == 'draft': picking.action_confirm() if picking.state != 'assigned': picking.action_assign() if picking.state != 'assigned': raise UserError( _("Could not reserve all requested products. Please use the \'Mark as Todo\' button to handle the reservation manually." )) for move in picking.move_lines.filtered( lambda m: m.state not in ['done', 'cancel']): for move_line in move.move_line_ids: move_line.qty_done = move_line.product_uom_qty if picking._check_backorder(): pick_to_backorder |= picking continue pick_to_do |= picking # Process every picking that do not require a backorder, then return a single backorder wizard for every other ones. if pick_to_do: pick_to_do.action_done() if pick_to_backorder: return pick_to_backorder.action_generate_backorder_wizard() return False
class EventRegistration(models.Model): """ Store answers on attendees. """ _inherit = 'event.registration' answer_ids = fields.Many2many('event.answer', 'event_registration_answer', string='Answers')
class HolidaysSummaryEmployee(models.TransientModel): _name = 'hr.holidays.summary.employee' _description = 'HR Time Off Summary Report By Employee' date_from = fields.Date(string='From', required=True, default=lambda *a: time.strftime('%Y-%m-01')) emp = fields.Many2many('hr.employee', 'summary_emp_rel', 'sum_id', 'emp_id', string='Employee(s)') holiday_type = fields.Selection([('Approved', 'Approved'), ('Confirmed', 'Confirmed'), ('both', 'Both Approved and Confirmed')], string='Select Time Off Type', required=True, default='Approved') def print_report(self): self.ensure_one() [data] = self.read() data['emp'] = self.env.context.get('active_ids', []) employees = self.env['hr.employee'].browse(data['emp']) datas = {'ids': [], 'model': 'hr.employee', 'form': data} return self.env.ref( 'hr_holidays.action_report_holidayssummary').report_action( employees, data=datas)
class Tags(models.Model): _name = 'res.partner.tag' _description = 'Partner Tags - These tags can be used on website to find customers by sector, or ...' _inherit = 'website.published.mixin' @api.model def get_selection_class(self): classname = ['default', 'primary', 'success', 'warning', 'danger'] return [(x, str.title(x)) for x in classname] name = fields.Char('Category Name', required=True, translate=True) partner_ids = fields.Many2many('res.partner', 'res_partner_res_partner_tag_rel', 'tag_id', 'partner_id', string='Partners') classname = fields.Selection(get_selection_class, 'Class', default='default', help="Bootstrap class to customize the color", required=True) active = fields.Boolean('Active', default=True) def _default_is_published(self): return True
class StockWarnInsufficientQty(models.AbstractModel): _name = 'stock.warn.insufficient.qty' _description = 'Warn Insufficient Quantity' product_id = fields.Many2one('product.product', 'Product', required=True) location_id = fields.Many2one('stock.location', 'Location', domain="[('usage', '=', 'internal')]", required=True) quant_ids = fields.Many2many('stock.quant', compute='_compute_quant_ids') def _get_reference_document_company_id(self): raise NotImplementedError() @api.depends('product_id') def _compute_quant_ids(self): for quantity in self: quantity.quant_ids = self.env['stock.quant'].search([ ('product_id', '=', quantity.product_id.id), ('location_id.usage', '=', 'internal'), ('company_id', '=', quantity._get_reference_document_company_id().id) ]) def action_done(self): raise NotImplementedError()
class AccountCommonReport(models.TransientModel): _name = "account.common.report" _description = "Account Common Report" company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.company) journal_ids = fields.Many2many( 'account.journal', string='Journals', required=True, default=lambda self: self.env['account.journal'].search([( 'company_id', '=', self.company_id.id)])) date_from = fields.Date(string='Start Date') date_to = fields.Date(string='End Date') target_move = fields.Selection([ ('posted', 'All Posted Entries'), ('all', 'All Entries'), ], string='Target Moves', required=True, default='posted') @api.onchange('company_id') def _onchange_company_id(self): if self.company_id: self.journal_ids = self.env['account.journal'].search([ ('company_id', '=', self.company_id.id) ]) else: self.journal_ids = self.env['account.journal'].search([]) def _build_contexts(self, data): result = {} result['journal_ids'] = 'journal_ids' in data['form'] and data['form'][ 'journal_ids'] or False result['state'] = 'target_move' in data['form'] and data['form'][ 'target_move'] or '' result['date_from'] = data['form']['date_from'] or False result['date_to'] = data['form']['date_to'] or False result['strict_range'] = True if result['date_from'] else False result['company_id'] = data['form']['company_id'][0] or False return result def _print_report(self, data): raise NotImplementedError() def check_report(self): self.ensure_one() data = {} data['ids'] = self.env.context.get('active_ids', []) data['model'] = self.env.context.get('active_model', 'ir.ui.menu') data['form'] = self.read([ 'date_from', 'date_to', 'journal_ids', 'target_move', 'company_id' ])[0] used_context = self._build_contexts(data) data['form']['used_context'] = dict(used_context, lang=get_lang(self.env).code) return self.with_context(discard_logo_check=True)._print_report(data)
class ResUsers(models.Model): _inherit = 'res.users' last_lunch_location_id = fields.Many2one('lunch.location') favorite_lunch_product_ids = fields.Many2many( 'lunch.product', 'lunch_product_favorite_user_rel', 'user_id', 'product_id')
class AccountMoveLine(models.Model): _inherit = 'account.move.line' # Overload of fields defined in account analytic_account_id = fields.Many2one(compute="_compute_analytic_account", store=True, readonly=False) analytic_tag_ids = fields.Many2many(compute="_compute_analytic_account", store=True, readonly=False) @api.depends('product_id', 'account_id', 'partner_id', 'date_maturity') def _compute_analytic_account(self): for record in self: record.analytic_account_id = (record._origin or record).analytic_account_id record.analytic_tag_ids = (record._origin or record).analytic_tag_ids rec = self.env['account.analytic.default'].account_get( product_id=record.product_id.id, partner_id=record.partner_id.commercial_partner_id.id or record.move_id.partner_id.commercial_partner_id.id, account_id=record.account_id.id, user_id=record.env.uid, date=record.date_maturity, company_id=record.move_id.company_id.id) if rec and not record.exclude_from_invoice_tab: record.analytic_account_id = rec.analytic_id record.analytic_tag_ids = rec.analytic_tag_ids
class Container(models.Model): _name = 'test_access_right.container' _description = 'Test Access Right Container' some_ids = fields.Many2many('test_access_right.some_obj', 'test_access_right_rel', 'container_id', 'some_id')
class Tags(models.Model): _name = "forum.tag" _description = "Forum Tag" _inherit = ['mail.thread', 'website.seo.metadata'] name = fields.Char('Name', required=True) forum_id = fields.Many2one('forum.forum', string='Forum', required=True) post_ids = fields.Many2many( 'forum.post', 'forum_tag_rel', 'forum_tag_id', 'forum_id', string='Posts', domain=[('state', '=', 'active')]) posts_count = fields.Integer('Number of Posts', compute='_get_posts_count', store=True) _sql_constraints = [ ('name_uniq', 'unique (name, forum_id)', "Tag name already exists !"), ] @api.depends("post_ids.tag_ids", "post_ids.state") def _get_posts_count(self): for tag in self: tag.posts_count = len(tag.post_ids) @api.model def create(self, vals): forum = self.env['forum.forum'].browse(vals.get('forum_id')) if self.env.user.karma < forum.karma_tag_create: raise AccessError(_('%d karma required to create a new Tag.') % forum.karma_tag_create) return super(Tags, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(vals)
class BaseModel(models.Model): _name = 'test_performance.base' _description = 'Test Performance Base' name = fields.Char() value = fields.Integer(default=0) value_pc = fields.Float(compute="_value_pc", store=True) value_ctx = fields.Float(compute="_value_ctx") partner_id = fields.Many2one('res.partner', string='Customer') line_ids = fields.One2many('test_performance.line', 'base_id') total = fields.Integer(compute="_total", store=True) tag_ids = fields.Many2many('test_performance.tag') @api.depends('value') def _value_pc(self): for record in self: record.value_pc = float(record.value) / 100 @api.depends_context('key') def _value_ctx(self): self.env.cr.execute('SELECT 42') # one dummy query per batch for record in self: record.value_ctx = self.env.context.get('key') @api.depends('line_ids.value') def _total(self): for record in self: record.total = sum(line.value for line in record.line_ids)
class StockBackorderConfirmation(models.TransientModel): _name = 'stock.backorder.confirmation' _description = 'Backorder Confirmation' pick_ids = fields.Many2many('stock.picking', 'stock_picking_backorder_rel') def _process(self, cancel_backorder=False): for confirmation in self: if cancel_backorder: for pick_id in confirmation.pick_ids: moves_to_log = {} for move in pick_id.move_lines: if float_compare(move.product_uom_qty, move.quantity_done, precision_rounding=move.product_uom. rounding) > 0: moves_to_log[move] = (move.quantity_done, move.product_uom_qty) pick_id._log_less_quantities_than_expected(moves_to_log) confirmation.pick_ids.with_context( cancel_backorder=cancel_backorder).action_done() def process(self): self._process() def process_cancel_backorder(self): self._process(cancel_backorder=True)
class ChooseDestinationLocation(models.TransientModel): _name = 'stock.package.destination' _description = 'Stock Package Destination' picking_id = fields.Many2one('stock.picking', required=True) move_line_ids = fields.Many2many('stock.move.line', 'Products', compute='_compute_move_line_ids', required=True) location_dest_id = fields.Many2one('stock.location', 'Destination location', required=True) filtered_location = fields.One2many(comodel_name='stock.location', compute='_filter_location') @api.depends('picking_id') def _compute_move_line_ids(self): for destination in self: destination.move_line_ids = destination.picking_id.move_line_ids.filtered( lambda l: l.qty_done > 0 and not l.result_package_id) @api.depends('move_line_ids') def _filter_location(self): for destination in self: destination.filtered_location = destination.move_line_ids.mapped( 'location_dest_id') def action_done(self): # set the same location on each move line and pass again in _put_in_pack for line in self.move_line_ids: line.location_dest_id = self.location_dest_id return self.picking_id.put_in_pack()
class BaseLanguageInstall(models.TransientModel): _inherit = "base.language.install" website_ids = fields.Many2many('website', string='Websites to translate') @api.model def default_get(self, fields): defaults = super(BaseLanguageInstall, self).default_get(fields) website_id = self._context.get('params', {}).get('website_id') if website_id: if 'website_ids' not in defaults: defaults['website_ids'] = [] defaults['website_ids'].append(website_id) return defaults def lang_install(self): action = super(BaseLanguageInstall, self).lang_install() lang = self.env['res.lang']._lang_get(self.lang) if self.website_ids and lang: self.website_ids.write({'language_ids': [(4, lang.id)]}) params = self._context.get('params', {}) if 'url_return' in params: return { 'url': params['url_return'].replace('[lang]', self.lang), 'type': 'ir.actions.act_url', 'target': 'self' } return action
class Category(models.Model): _name = 'test_new_api.category' _description = 'Test New API Category' _order = 'name' _parent_store = True _parent_name = 'parent' name = fields.Char(required=True) color = fields.Integer('Color Index') parent = fields.Many2one('test_new_api.category', ondelete='cascade') parent_path = fields.Char(index=True) root_categ = fields.Many2one(_name, compute='_compute_root_categ') display_name = fields.Char(compute='_compute_display_name', inverse='_inverse_display_name') dummy = fields.Char(store=False) discussions = fields.Many2many('test_new_api.discussion', 'test_new_api_discussion_category', 'category', 'discussion') _sql_constraints = [ ('positive_color', 'CHECK(color >= 0)', 'The color code must be positive !') ] @api.depends('name', 'parent.display_name') # this definition is recursive def _compute_display_name(self): for cat in self: if cat.parent: cat.display_name = cat.parent.display_name + ' / ' + cat.name else: cat.display_name = cat.name @api.depends('parent') def _compute_root_categ(self): for cat in self: current = cat while current.parent: current = current.parent cat.root_categ = current def _inverse_display_name(self): for cat in self: names = cat.display_name.split('/') # determine sequence of categories categories = [] for name in names[:-1]: category = self.search([('name', 'ilike', name.strip())]) categories.append(category[0]) categories.append(cat) # assign parents following sequence for parent, child in zip(categories, categories[1:]): if parent and child: child.parent = parent # assign name of last category, and reassign display_name (to normalize it) cat.name = names[-1].strip() def _read(self, fields): # DLE P45: `test_31_prefetch`, # with self.assertRaises(AccessError): # cat1.name if self.search_count([('id', 'in', self._ids), ('name', '=', 'NOACCESS')]): raise AccessError('Sorry') return super(Category, self)._read(fields)
class BaseLanguageExport(models.TransientModel): _name = "base.language.export" _description = 'Language Export' @api.model def _get_languages(self): langs = self.env['res.lang'].get_installed() return [(NEW_LANG_KEY, _('New Language (Empty translation template)'))] + \ langs name = fields.Char('File Name', readonly=True) lang = fields.Selection(_get_languages, string='Language', required=True, default=NEW_LANG_KEY) format = fields.Selection([('csv', 'CSV File'), ('po', 'PO File'), ('tgz', 'TGZ Archive')], string='File Format', required=True, default='csv') modules = fields.Many2many('ir.module.module', 'rel_modules_langexport', 'wiz_id', 'module_id', string='Apps To Export', domain=[('state', '=', 'installed')]) data = fields.Binary('File', readonly=True, attachment=False) state = fields.Selection( [('choose', 'choose'), ('get', 'get')], # choose language or get the file default='choose') def act_getfile(self): this = self[0] lang = this.lang if this.lang != NEW_LANG_KEY else False mods = sorted(this.mapped('modules.name')) or ['all'] with contextlib.closing(io.BytesIO()) as buf: tools.trans_export(lang, mods, buf, this.format, self._cr) out = base64.encodestring(buf.getvalue()) filename = 'new' if lang: filename = tools.get_iso_codes(lang) elif len(mods) == 1: filename = mods[0] extension = this.format if not lang and extension == 'po': extension = 'pot' name = "%s.%s" % (filename, extension) this.write({'state': 'get', 'data': out, 'name': name}) return { 'type': 'ir.actions.act_window', 'res_model': 'base.language.export', 'view_mode': 'form', 'res_id': this.id, 'views': [(False, 'form')], 'target': 'new', }
class WebsiteVisitor(models.Model): _inherit = 'website.visitor' lead_ids = fields.Many2many('crm.lead', string='Leads', groups="sales_team.group_sale_salesman") lead_count = fields.Integer('# Leads', compute="_compute_lead_count", groups="sales_team.group_sale_salesman") @api.depends('lead_ids') def _compute_lead_count(self): for visitor in self: visitor.lead_count = len(visitor.lead_ids) @api.depends('partner_id.email_normalized', 'partner_id.mobile', 'lead_ids.email_normalized', 'lead_ids.mobile') def _compute_email_phone(self): super(WebsiteVisitor, self)._compute_email_phone() self.flush() left_visitors = self.filtered( lambda visitor: not visitor.email or not visitor.mobile) leads = left_visitors.mapped('lead_ids').sorted('create_date', reverse=True) visitor_to_lead_ids = dict( (visitor.id, visitor.lead_ids.ids) for visitor in left_visitors) for visitor in left_visitors: visitor_leads = leads.filtered( lambda lead: lead.id in visitor_to_lead_ids[visitor.id]) if not visitor.email: visitor.email = next( (lead.email_normalized for lead in visitor_leads if lead.email_normalized), False) if not visitor.mobile: visitor.mobile = next( (lead.mobile or lead.phone for lead in visitor_leads if lead.mobile or lead.phone), False) def _prepare_visitor_send_mail_values(self): visitor_mail_values = super(WebsiteVisitor, self)._prepare_visitor_send_mail_values() if self.lead_ids: lead = self.lead_ids._sort_by_confidence_level(reverse=True)[0] partner_id = self.partner_id.id if not self.partner_id: partner_id = lead.handle_partner_assignation()[lead.id] if not lead.partner_id: lead.partner_id = partner_id self.partner_id = partner_id return { 'res_model': 'crm.lead', 'res_id': lead.id, 'partner_ids': [partner_id], } return visitor_mail_values
class HrPlan(models.Model): _name = 'hr.plan' _description = 'plan' name = fields.Char('Name', required=True) plan_activity_type_ids = fields.Many2many('hr.plan.activity.type', string='Activities') active = fields.Boolean(default=True)
class ResCountryGroup(models.Model): _inherit = 'res.country.group' pricelist_ids = fields.Many2many('product.pricelist', 'res_country_group_pricelist_rel', 'res_country_group_id', 'pricelist_id', string='Pricelists')
class ProductAttribute(models.Model): _inherit = ['product.attribute'] is_quick_filter = fields.Boolean( string='Quick Filter', help="It will show this attribute in quick filter") website_ids = fields.Many2many( 'website', help="You can set the filter in particular website.")
class Discussion(models.Model): _name = 'test_new_api.discussion' _description = 'Test New API Discussion' name = fields.Char(string='Title', required=True, help="General description of what this discussion is about.") moderator = fields.Many2one('res.users') categories = fields.Many2many('test_new_api.category', 'test_new_api_discussion_category', 'discussion', 'category') participants = fields.Many2many('res.users', context={'active_test': False}) messages = fields.One2many('test_new_api.message', 'discussion', copy=True) message_concat = fields.Text(string='Message concatenate') important_messages = fields.One2many('test_new_api.message', 'discussion', domain=[('important', '=', True)]) very_important_messages = fields.One2many( 'test_new_api.message', 'discussion', domain=lambda self: self._domain_very_important()) emails = fields.One2many('test_new_api.emailmessage', 'discussion') important_emails = fields.One2many('test_new_api.emailmessage', 'discussion', domain=[('important', '=', True)]) def _domain_very_important(self): """Ensure computed O2M domains work as expected.""" return [("important", "=", True)] @api.onchange('name') def _onchange_name(self): # test onchange modifying one2many field values if self.env.context.get('generate_dummy_message') and self.name == '{generate_dummy_message}': # update body of existings messages and emails for message in self.messages: message.body = 'not last dummy message' for message in self.important_messages: message.body = 'not last dummy message' # add new dummy message message_vals = self.messages._add_missing_default_values({'body': 'dummy message', 'important': True}) self.messages |= self.messages.new(message_vals) self.important_messages |= self.messages.new(message_vals) @api.onchange('moderator') def _onchange_moderator(self): self.participants |= self.moderator @api.onchange('messages') def _onchange_messages(self): self.message_concat = "\n".join(["%s:%s" % (m.name, m.body) for m in self.messages])
class MultiLine(models.Model): _name = 'test_new_api.multi.line' _description = 'Test New API Multi Line' multi = fields.Many2one('test_new_api.multi', ondelete='cascade') name = fields.Char() partner = fields.Many2one('res.partner') tags = fields.Many2many('test_new_api.multi.tag')