class Employee(models.Model): _inherit = 'hr.employee' resume_line_ids = fields.One2many('hr.resume.line', 'employee_id', string="Resumé lines") employee_skill_ids = fields.One2many('hr.employee.skill', 'employee_id', string="Skills") @api.model_create_multi def create(self, vals_list): res = super(Employee, self).create(vals_list) resume_lines_values = [] for employee in res: line_type = self.env.ref('hr_skills.resume_type_experience', raise_if_not_found=False) resume_lines_values.append({ 'employee_id': employee.id, 'name': employee.company_id.name or '', 'date_start': employee.create_date.date(), 'description': employee.job_title or '', 'line_type_id': line_type and line_type.id, }) self.env['hr.resume.line'].create(resume_lines_values) return res
class EventEvent(models.Model): """ Override Event model to add optional questions when buying tickets. """ _inherit = 'event.event' question_ids = fields.One2many('event.question', 'event_id', 'Questions', copy=True) general_question_ids = fields.One2many('event.question', 'event_id', 'General Questions', domain=[('is_individual', '=', False)]) specific_question_ids = fields.One2many('event.question', 'event_id', 'Specific Questions', domain=[('is_individual', '=', True)]) @api.onchange('event_type_id') def _onchange_type(self): super(EventEvent, self)._onchange_type() if self.event_type_id.use_questions and self.event_type_id.question_ids: self.question_ids = [(5, 0, 0)] + [ (0, 0, { 'title': question.title, 'sequence': question.sequence, 'is_individual': question.is_individual, }) for question in self.event_type_id.question_ids ]
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 SkillType(models.Model): _name = 'hr.skill.type' _description = "Skill Type" name = fields.Char(required=True) skill_ids = fields.One2many('hr.skill', 'skill_type_id', string="Skills", ondelete='cascade') skill_level_ids = fields.One2many('hr.skill.level', 'skill_type_id', string="Levels", ondelete='cascade')
class One2ManyMultiple(models.Model): _name = 'export.one2many.multiple' _description = 'Export One To Many Multiple' parent_id = fields.Many2one('export.one2many.recursive') const = fields.Integer(default=36) child1 = fields.One2many('export.one2many.child.1', 'parent_id') child2 = fields.One2many('export.one2many.child.2', 'parent_id')
class EmployeePublic(models.Model): _inherit = 'hr.employee.public' resume_line_ids = fields.One2many('hr.resume.line', 'employee_id', string="Resumé lines") employee_skill_ids = fields.One2many('hr.employee.skill', 'employee_id', string="Skills")
class ModuleCategory(models.Model): _name = "ir.module.category" _description = "Application" _order = 'name' @api.depends('module_ids') def _compute_module_nr(self): cr = self._cr cr.execute( 'SELECT category_id, COUNT(*) \ FROM ir_module_module \ WHERE category_id IN %(ids)s \ OR category_id IN (SELECT id \ FROM ir_module_category \ WHERE parent_id IN %(ids)s) \ GROUP BY category_id', {'ids': tuple(self.ids)}) result = dict(cr.fetchall()) for cat in self.filtered('id'): cr.execute('SELECT id FROM ir_module_category WHERE parent_id=%s', (cat.id, )) cat.module_nr = sum([result.get(c, 0) for (c, ) in cr.fetchall()], result.get(cat.id, 0)) name = fields.Char(string='Name', required=True, translate=True, index=True) parent_id = fields.Many2one('ir.module.category', string='Parent Application', index=True) child_ids = fields.One2many('ir.module.category', 'parent_id', string='Child Applications') module_nr = fields.Integer(string='Number of Apps', compute='_compute_module_nr') module_ids = fields.One2many('ir.module.module', 'category_id', string='Modules') description = fields.Text(string='Description', translate=True) sequence = fields.Integer(string='Sequence') visible = fields.Boolean(string='Visible', default=True) exclusive = fields.Boolean(string='Exclusive') xml_id = fields.Char(string='External ID', compute='_compute_xml_id') def _compute_xml_id(self): xml_ids = defaultdict(list) domain = [('model', '=', self._name), ('res_id', 'in', self.ids)] for data in self.env['ir.model.data'].sudo().search_read( domain, ['module', 'name', 'res_id']): xml_ids[data['res_id']].append("%s.%s" % (data['module'], data['name'])) for cat in self: cat.xml_id = xml_ids.get(cat.id, [''])[0]
class ResCompany(models.Model): _inherit = 'res.company' resource_calendar_ids = fields.One2many('resource.calendar', 'company_id', 'Working Hours') resource_calendar_id = fields.Many2one('resource.calendar', 'Default Working Hours', ondelete='restrict') @api.model def _init_data_resource_calendar(self): self.search([('resource_calendar_id', '=', False) ])._create_resource_calendar() def _create_resource_calendar(self): for company in self: company.resource_calendar_id = self.env[ 'resource.calendar'].create({ 'name': _('Standard 40 hours/week'), 'company_id': company.id }).id @api.model def create(self, values): company = super(ResCompany, self).create(values) if not company.resource_calendar_id: company.sudo()._create_resource_calendar() # calendar created from form view: no company_id set because record was still not created if not company.resource_calendar_id.company_id: company.resource_calendar_id.company_id = company.id return company
class EventType(models.Model): _inherit = 'event.type' @api.model def _get_default_event_ticket_ids(self): product = self.env.ref('event_sale.product_product_event', raise_if_not_found=False) if not product: return False return [(0, 0, { 'name': _('Registration'), 'product_id': product.id, 'price': 0, })] use_ticketing = fields.Boolean('Ticketing') event_ticket_ids = fields.One2many('event.event.ticket', 'event_type_id', string='Tickets', default=_get_default_event_ticket_ids) @api.onchange('name') def _onchange_name(self): if self.name: self.event_ticket_ids.filtered( lambda ticket: ticket.name == _('Registration')).update( {'name': _('Registration for %s') % self.name})
class Event(models.Model): _inherit = 'event.event' event_ticket_ids = fields.One2many('event.event.ticket', 'event_id', string='Event Ticket', copy=True) @api.onchange('event_type_id') def _onchange_type(self): super(Event, self)._onchange_type() if self.event_type_id.use_ticketing: self.event_ticket_ids = [(5, 0, 0)] + [(0, 0, { 'name': self.name and _('Registration for %s') % self.name or ticket.name, 'product_id': ticket.product_id.id, 'price': ticket.price, }) for ticket in self.event_type_id.event_ticket_ids] def _is_event_registrable(self): if super(Event, self)._is_event_registrable(): self.ensure_one() return all( self.event_ticket_ids.with_context( active_test=False).mapped(lambda t: t.product_id.active)) else: return False
class report_paperformat(models.Model): _name = "report.paperformat" _description = "Paper Format Config" name = fields.Char('Name', required=True) default = fields.Boolean('Default paper format ?') format = fields.Selection([(ps['key'], ps['description']) for ps in PAPER_SIZES], 'Paper size', default='A4', help="Select Proper Paper size") margin_top = fields.Float('Top Margin (mm)', default=40) margin_bottom = fields.Float('Bottom Margin (mm)', default=20) margin_left = fields.Float('Left Margin (mm)', default=7) margin_right = fields.Float('Right Margin (mm)', default=7) page_height = fields.Integer('Page height (mm)', default=False) page_width = fields.Integer('Page width (mm)', default=False) orientation = fields.Selection([('Landscape', 'Landscape'), ('Portrait', 'Portrait')], 'Orientation', default='Landscape') header_line = fields.Boolean('Display a header line', default=False) header_spacing = fields.Integer('Header spacing', default=35) dpi = fields.Integer('Output DPI', required=True, default=90) report_ids = fields.One2many('ir.actions.report', 'paperformat_id', 'Associated reports', help="Explicitly associated reports") print_page_width = fields.Float('Print page width (mm)', compute='_compute_print_page_size') print_page_height = fields.Float('Print page height (mm)', compute='_compute_print_page_size') @api.constrains('format') def _check_format_or_page(self): if self.filtered(lambda x: x.format != 'custom' and (x.page_width or x.page_height)): raise ValidationError( _('You can select either a format or a specific page width/height, but not both.' )) def _compute_print_page_size(self): for record in self: width = height = 0.0 if record.format: if record.format == 'custom': width = record.page_width height = record.page_height else: paper_size = next(ps for ps in PAPER_SIZES if ps['key'] == record.format) width = paper_size['width'] height = paper_size['height'] if record.orientation == 'Landscape': # swap sizes width, height = height, width record.print_page_width = width record.print_page_height = height
class MrpRouting(models.Model): """ Specifies routings of work centers """ _name = 'mrp.routing' _description = 'Routings' name = fields.Char('Routing', required=True) active = fields.Boolean( 'Active', default=True, help= "If the active field is set to False, it will allow you to hide the routing without removing it." ) code = fields.Char('Reference', copy=False, default=lambda self: _('New'), readonly=True) note = fields.Text('Description') operation_ids = fields.One2many('mrp.routing.workcenter', 'routing_id', 'Operations', copy=True) company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.company) @api.model def create(self, vals): if 'code' not in vals or vals['code'] == _('New'): vals['code'] = self.env['ir.sequence'].next_by_code( 'mrp.routing') or _('New') return super(MrpRouting, self).create(vals)
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 SaleOrderTemplate(models.Model): _name = "sale.order.template" _description = "Quotation Template" def _get_default_require_signature(self): return self.env.company.portal_confirmation_sign def _get_default_require_payment(self): return self.env.company.portal_confirmation_pay name = fields.Char('Quotation Template', required=True) sale_order_template_line_ids = fields.One2many('sale.order.template.line', 'sale_order_template_id', 'Lines', copy=True) note = fields.Text('Terms and conditions', translate=True) sale_order_template_option_ids = fields.One2many('sale.order.template.option', 'sale_order_template_id', 'Optional Products', copy=True) number_of_days = fields.Integer('Quotation Duration', help='Number of days for the validity date computation of the quotation') require_signature = fields.Boolean('Online Signature', default=_get_default_require_signature, help='Request a online signature to the customer in order to confirm orders automatically.') require_payment = fields.Boolean('Online Payment', default=_get_default_require_payment, help='Request an online payment to the customer in order to confirm orders automatically.') mail_template_id = fields.Many2one( 'mail.template', 'Confirmation Mail', domain=[('model', '=', 'sale.order')], help="This e-mail template will be sent on confirmation. Leave empty to send nothing.") active = fields.Boolean(default=True, help="If unchecked, it will allow you to hide the quotation template without removing it.") company_id = fields.Many2one('res.company', string='Company') @api.constrains('company_id', 'sale_order_template_line_ids', 'sale_order_template_option_ids') def _check_company_id(self): for template in self: companies = template.mapped('sale_order_template_line_ids.product_id.company_id') | template.mapped('sale_order_template_option_ids.product_id.company_id') if len(companies) > 1: raise ValidationError(_("Your template cannot contain products from multiple companies.")) elif companies and companies != template.company_id: raise ValidationError((_("Your template contains products from company %s whereas your template belongs to company %s. \n Please change the company of your template or remove the products from other companies.") % (companies.mapped('display_name'), template.company_id.display_name))) @api.onchange('sale_order_template_line_ids', 'sale_order_template_option_ids') def _onchange_template_line_ids(self): companies = self.mapped('sale_order_template_option_ids.product_id.company_id') | self.mapped('sale_order_template_line_ids.product_id.company_id') if companies and self.company_id not in companies: self.company_id = companies[0] def write(self, vals): if 'active' in vals and not vals.get('active'): template_id = self.env['ir.default'].get('sale.order', 'sale_order_template_id') for template in self: if template_id and template_id == template.id: raise UserError(_('Before archiving "%s" please select another default template in the settings.') % template.name) return super(SaleOrderTemplate, self).write(vals)
class O2MRecursive(models.Model): _name = _description = 'test_testing_utilities.recursive' one_to_many_id = fields.Many2one('test_testing_utilities.recursive', readonly=True) many_to_one_ids = fields.One2many('test_testing_utilities.recursive', 'one_to_many_id', readonly=True)
class Employee(models.Model): _inherit = ["hr.employee"] subordinate_ids = fields.One2many('hr.employee', string='Subordinates', compute='_compute_subordinates', help="Direct and indirect subordinates", compute_sudo=True)
class ModelParentM2o(models.Model): _name = 'test_new_api.model_parent_m2o' _description = 'dummy model with multiple childs' name = fields.Char('Name') child_ids = fields.One2many('test_new_api.model_child_m2o', 'parent_id', string="Children")
class ResCompany(models.Model): _inherit = "res.company" ldaps = fields.One2many('res.company.ldap', 'company', string='LDAP Parameters', copy=True, groups="base.group_system")
class Movie(models.Model): _name = 'test_new_api.creativework.movie' _description = 'Test New API Creative Work Movie' name = fields.Char() editions = fields.One2many('test_new_api.creativework.edition', 'res_id', domain=[('res_model', '=', _name)])
class ResUsers(models.Model): _inherit = 'res.users' resource_ids = fields.One2many( 'resource.resource', 'user_id', 'Resources') resource_calendar_id = fields.Many2one( 'resource.calendar', 'Default Working Hours', related='resource_ids.calendar_id', readonly=False)
class EventType(models.Model): _inherit = 'event.type' use_questions = fields.Boolean('Questions to Attendees') question_ids = fields.One2many('event.question', 'event_type_id', string='Questions', copy=True)
class AccountAnalyticTag(models.Model): _name = 'account.analytic.tag' _description = 'Analytic Tags' name = fields.Char(string='Analytic Tag', index=True, required=True) color = fields.Integer('Color Index') active = fields.Boolean(default=True, help="Set active to false to hide the Analytic Tag without removing it.") active_analytic_distribution = fields.Boolean('Analytic Distribution') analytic_distribution_ids = fields.One2many('account.analytic.distribution', 'tag_id', string="Analytic Accounts") company_id = fields.Many2one('res.company', string='Company')
class ProductCategory(models.Model): _name = "product.category" _description = "Product Category" _parent_name = "parent_id" _parent_store = True _rec_name = 'complete_name' _order = 'complete_name' name = fields.Char('Name', index=True, required=True) complete_name = fields.Char('Complete Name', compute='_compute_complete_name', store=True) parent_id = fields.Many2one('product.category', 'Parent Category', index=True, ondelete='cascade') parent_path = fields.Char(index=True) child_id = fields.One2many('product.category', 'parent_id', 'Child Categories') product_count = fields.Integer( '# Products', compute='_compute_product_count', help= "The number of products under this category (Does not consider the children categories)" ) @api.depends('name', 'parent_id.complete_name') def _compute_complete_name(self): for category in self: if category.parent_id: category.complete_name = '%s / %s' % ( category.parent_id.complete_name, category.name) else: category.complete_name = category.name def _compute_product_count(self): read_group_res = self.env['product.template'].read_group( [('categ_id', 'child_of', self.ids)], ['categ_id'], ['categ_id']) group_data = dict((data['categ_id'][0], data['categ_id_count']) for data in read_group_res) for categ in self: product_count = 0 for sub_categ_id in categ.search([('id', 'child_of', categ.ids) ]).ids: product_count += group_data.get(sub_categ_id, 0) categ.product_count = product_count @api.constrains('parent_id') def _check_category_recursion(self): if not self._check_recursion(): raise ValidationError(_('You cannot create recursive categories.')) return True @api.model def name_create(self, name): return self.create({'name': name}).name_get()[0]
class GamificationBadge(models.Model): _inherit = 'gamification.badge' survey_ids = fields.One2many('survey.survey', 'certification_badge_id', 'Survey Ids') survey_id = fields.Many2one('survey.survey', 'Survey', compute='_compute_survey_id', store=True) @api.depends('survey_ids.certification_badge_id') def _compute_survey_id(self): for badge in self: badge.survey_id = badge.survey_ids[0] if badge.survey_ids else None
class AttachmentHost(models.Model): _name = 'test_new_api.attachment.host' _description = 'Attachment Host' attachment_ids = fields.One2many( 'test_new_api.attachment', 'res_id', auto_join=True, domain=lambda self: [('res_model', '=', self._name)], )
class Employee(models.Model): _inherit = 'hr.employee' equipment_ids = fields.One2many('maintenance.equipment', 'employee_id') equipment_count = fields.Integer('Equipments', compute='_compute_equipment_count') @api.depends('equipment_ids') def _compute_equipment_count(self): for employee in self: employee.equipment_count = len(employee.equipment_ids)
class Product(models.Model): _inherit = 'product.product' event_ticket_ids = fields.One2many('event.event.ticket', 'product_id', string='Event Tickets') @api.onchange('event_ok') def _onchange_event_ok(self): """ Redirection, inheritance mechanism hides the method on the model """ if self.event_ok: self.type = 'service'
class StockTrackConfirmation(models.TransientModel): _name = 'stock.track.confirmation' _description = 'Stock Track Confirmation' tracking_line_ids = fields.One2many('stock.track.line', 'wizard_id') inventory_id = fields.Many2one('stock.inventory', 'Inventory') def action_confirm(self): for confirmation in self: confirmation.inventory_id._action_done()
class RegistrationEditor(models.TransientModel): _name = "registration.editor" _description = 'Edit Attendee Details on Sales Confirmation' sale_order_id = fields.Many2one('sale.order', 'Sales Order', required=True) event_registration_ids = fields.One2many('registration.editor.line', 'editor_id', string='Registrations to Edit') @api.model def default_get(self, fields): res = super(RegistrationEditor, self).default_get(fields) if not res.get('sale_order_id'): sale_order_id = res.get('sale_order_id', self._context.get('active_id')) res['sale_order_id'] = sale_order_id sale_order = self.env['sale.order'].browse(res.get('sale_order_id')) registrations = self.env['event.registration'].search([ ('sale_order_id', '=', sale_order.id), ('event_ticket_id', 'in', sale_order.mapped('order_line.event_ticket_id').ids), ('state', '!=', 'cancel')]) attendee_list = [] for so_line in [l for l in sale_order.order_line if l.event_ticket_id]: existing_registrations = [r for r in registrations if r.event_ticket_id == so_line.event_ticket_id] for reg in existing_registrations: attendee_list.append([0, 0, { 'event_id': reg.event_id.id, 'event_ticket_id': reg.event_ticket_id.id, 'registration_id': reg.id, 'name': reg.name, 'email': reg.email, 'phone': reg.phone, 'mobile': reg.mobile, 'sale_order_line_id': so_line.id, }]) for count in range(int(so_line.product_uom_qty) - len(existing_registrations)): attendee_list.append([0, 0, { 'event_id': so_line.event_id.id, 'event_ticket_id': so_line.event_ticket_id.id, 'sale_order_line_id': so_line.id, }]) res['event_registration_ids'] = attendee_list res = self._convert_to_write(res) return res def action_make_registration(self): self.ensure_one() for registration_line in self.event_registration_ids: values = registration_line.get_registration_data() if registration_line.registration_id: registration_line.registration_id.write(values) else: self.env['event.registration'].create(values) if self.env.context.get('active_model') == 'sale.order': for order in self.env['sale.order'].browse(self.env.context.get('active_ids', [])): order.order_line._update_registrations(confirm=False) return {'type': 'ir.actions.act_window_close'}
class O2MChange(models.Model): _name = 'test_testing_utilities.parent' _description = 'Testing Utilities Parent' value = fields.Integer(default=1) v = fields.Integer() subs = fields.One2many('test_testing_utilities.sub', 'parent_id') @api.onchange('value', 'subs') def _onchange_values(self): self.v = self.value + sum(s.value for s in self.subs)