class WebsiteResPartner(osv.Model): _name = 'res.partner' _inherit = [ 'res.partner', 'website.seo.metadata', 'website.published.mixin' ] def _get_ids(self, cr, uid, ids, flds, args, context=None): return {i: i for i in ids} def _set_private(self, cr, uid, ids, field_name, value, arg, context=None): return self.write(cr, uid, ids, {'website_published': not value}, context=context) def _get_private(self, cr, uid, ids, field_name, arg, context=None): return dict((rec.id, not rec.website_published) for rec in self.browse(cr, uid, ids, context=context)) def _search_private(self, cr, uid, obj, name, args, context=None): return [('website_published', '=', not args[0][2])] _columns = { 'website_private': fields.function(_get_private, fnct_inv=_set_private, fnct_search=_search_private, type='boolean', string='Private Profile'), 'website_description': fields.html('Website Partner Full Description', strip_style=True), 'website_short_description': fields.text('Website Partner Short Description'), # hack to allow using plain browse record in qweb views 'self': fields.function(_get_ids, type='many2one', relation=_name), } def _website_url(self, cr, uid, ids, field_name, arg, context=None): res = super(WebsiteResPartner, self)._website_url(cr, uid, ids, field_name, arg, context=context) for partner in self.browse(cr, uid, ids, context=context): res[partner.id] = "/partners/%s" % slug(partner) return res _defaults = { 'website_private': True, }
class module_category(osv.osv): _name = "ir.module.category" _description = "Application" def _module_nbr(self, cr, uid, ids, prop, unknow_none, context): 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(ids)}) result = dict(cr.fetchall()) for id in ids: cr.execute('select id from ir_module_category where parent_id=%s', (id, )) result[id] = sum([result.get(c, 0) for (c, ) in cr.fetchall()], result.get(id, 0)) return result _columns = { 'name': fields.char("Name", required=True, translate=True, select=True), 'parent_id': fields.many2one('ir.module.category', 'Parent Application', select=True), 'child_ids': fields.one2many('ir.module.category', 'parent_id', 'Child Applications'), 'module_nr': fields.function(_module_nbr, string='Number of Apps', type='integer'), 'module_ids': fields.one2many('ir.module.module', 'category_id', 'Modules'), 'description': fields.text("Description", translate=True), 'sequence': fields.integer('Sequence'), 'visible': fields.boolean('Visible'), 'xml_id': fields.function(osv.osv.get_external_id, type='char', string="External ID"), } _order = 'name' _defaults = { 'visible': 1, }
class product_product(osv.osv): _inherit = "product.product" def _bom_orders_count(self, cr, uid, ids, field_name, arg, context=None): Production = self.pool('mrp.production') res = {} for product_id in ids: res[product_id] = Production.search_count( cr, uid, [('product_id', '=', product_id)], context=context) return res _columns = { 'mo_count': fields.function(_bom_orders_count, string='# Manufacturing Orders', type='integer'), } def action_view_bom(self, cr, uid, ids, context=None): result = self.pool.get("product.template")._get_act_window_dict( cr, uid, 'mrp.product_open_bom', context=context) templates = [ product.product_tmpl_id.id for product in self.browse(cr, uid, ids, context=context) ] # bom specific to this variant or global to template context = { 'search_default_product_tmpl_id': templates[0], 'search_default_product_id': ids[0], 'default_product_tmpl_id': templates[0], 'default_product_id': ids[0], } result['context'] = str(context) return result
class website_published_mixin(osv.AbstractModel): _name = "website.published.mixin" _website_url_proxy = lambda self, *a, **kw: self._website_url(*a, **kw) _columns = { 'website_published': fields.boolean('Visible in Website', copy=False), 'website_url': fields.function( _website_url_proxy, type='char', string='Website URL', help='The full URL to access the document through the website.'), } def _website_url(self, cr, uid, ids, field_name, arg, context=None): return dict.fromkeys(ids, '#') def website_publish_button(self, cr, uid, ids, context=None): for i in self.browse(cr, uid, ids, context): if self.pool['res.users'].has_group( cr, uid, 'base.group_website_publisher') and i.website_url != '#': return self.open_website_url(cr, uid, ids, context) i.write({'website_published': not i.website_published}) return True def open_website_url(self, cr, uid, ids, context=None): return { 'type': 'ir.actions.act_url', 'url': self.browse(cr, uid, ids[0]).website_url, 'target': 'self', }
class res_partner(osv.osv): _name = 'res.partner' _inherit = 'res.partner' def _compute_payment_method_count(self, cr, uid, ids, field_names, arg, context=None): result = {} payment_data = self.pool['payment.method'].read_group( cr, uid, [('partner_id', 'in', ids)], ['partner_id'], ['partner_id'], context=context) mapped_data = dict([(payment['partner_id'][0], payment['partner_id_count']) for payment in payment_data]) for partner in self.browse(cr, uid, ids, context=context): result[partner.id] = mapped_data.get(partner.id, 0) return result _columns = { 'payment_method_ids': fields.one2many('payment.method', 'partner_id', 'Payment Methods'), 'payment_method_count': fields.function(_compute_payment_method_count, string='Count Payment Method', type="integer"), }
class hr_employee(osv.osv): _name = "hr.employee" _description = "Employee" _inherit = "hr.employee" def attachment_tree_view(self, cr, uid, ids, context): domain = ['&', ('res_model', '=', 'hr.employee'), ('res_id', 'in', ids)] res_id = ids and ids[0] or False return { 'name': _('Attachments'), 'domain': domain, 'res_model': 'ir.attachment', 'type': 'ir.actions.act_window', 'view_id': False, 'view_mode': 'kanban,tree,form', 'view_type': 'form', 'limit': 80, 'context': "{'default_res_model': '%s','default_res_id': %d}" % (self._name, res_id) } def _get_attached_docs(self, cr, uid, ids, field_name, arg, context): res = {} attachment = self.pool.get('ir.attachment') for id in ids: employee_attachments = attachment.search(cr, uid, [('res_model', '=', 'hr.employee'), ('res_id', '=', id)], context=context, count=True) res[id] = employee_attachments or 0 return res _columns = { 'doc_count': fields.function(_get_attached_docs, string="Number of documents attached", type='integer') }
class res_state(osv.osv): def name_get(self, cr, uid, ids, context=None): if not len(ids): return [] res = [] for state in self.browse(cr, uid, ids, context=context): data = [] acc = state while acc: data.insert(0, acc.name) acc = acc.parent_id data = ' / '.join(data) res.append((state.id, (state.code and '[' + state.code + '] ' or '') + data)) return res def complete_name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100): if not args: args = [] args = args[:] ids = [] if name: ids = self.search(cr, user, [('name', operator, name)]+ args, limit=limit) if not ids and len(name.split()) >= 2: #Separating code and name of account for searching operand1,operand2 = name.split(': ',1) #name can contain spaces e.g. eCore ids = self.search(cr, user, [('name', operator, operand2)]+ args, limit=limit) else: ids = self.search(cr, user, args, context=context, limit=limit) return self.name_get(cr, user, ids, context=context) def _name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None): if not ids: return [] res = [] for state in self.browse(cr, uid, ids, context=context): data = [] acc = state while acc: data.insert(0, acc.name) acc = acc.parent_id data = ' / '.join(data) res.append((state.id, data)) return dict(res) _name = 'res.country.state' _inherit = 'res.country.state' _columns = { 'code': fields.char('State Code', size=32,help='The state code.\n', required=True), 'complete_name': fields.function(_name_get_fnc, method=True, type="char", string='Complete Name', fnct_search=complete_name_search), 'parent_id': fields.many2one('res.country.state','Parent State', select=True, domain=[('type','=','view')]), 'child_ids': fields.one2many('res.country.state', 'parent_id', string='Child States'), 'type': fields.selection([('view','View'), ('normal','Normal')], 'Type'), } _defaults = { 'type': 'normal', }
class project_issue(osv.osv): _inherit = 'project.issue' _description = 'project issue' def _hours_get(self, cr, uid, ids, field_names, args, context=None): res = {} for issue in self.browse(cr, uid, ids, context=context): res[issue.id] = {'progress': issue.task_id.progress or 0.0} return res def _get_issue_task(self, cr, uid, task_ids, context=None): return self.pool['project.issue'].search(cr, uid, [('task_id', 'in', task_ids)], context=context) _columns = { 'progress': fields.function(_hours_get, string='Progress (%)', multi='line_id', group_operator="avg", help="Computed as: Time Spent / Total Time.", store={ 'project.issue': (lambda self, cr, uid, ids, c={}: ids, ['task_id'], 10), 'project.task': (_get_issue_task, ['progress'], 10), }), 'timesheet_ids': fields.one2many('account.analytic.line', 'issue_id', 'Timesheets'), 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'), } def on_change_project(self, cr, uid, ids, project_id, context=None): if not project_id: return {'value': {'analytic_account_id': False}} result = super(project_issue, self).on_change_project(cr, uid, ids, project_id, context=context) project = self.pool.get('project.project').browse(cr, uid, project_id, context=context) if 'value' not in result: result['value'] = {} account = project.analytic_account_id if account: result['value']['analytic_account_id'] = account.id return result
class stock_valuation_adjustment_lines(osv.osv): _name = 'stock.valuation.adjustment.lines' _description = 'Stock Valuation Adjustment Lines' def _amount_final(self, cr, uid, ids, name, args, context=None): result = {} for line in self.browse(cr, uid, ids, context=context): result[line.id] = { 'former_cost_per_unit': 0.0, 'final_cost': 0.0, } result[line.id]['former_cost_per_unit'] = (line.former_cost / line.quantity if line.quantity else 1.0) result[line.id]['final_cost'] = (line.former_cost + line.additional_landed_cost) return result def _get_name(self, cr, uid, ids, name, arg, context=None): res = {} for line in self.browse(cr, uid, ids, context=context): res[line.id] = line.product_id.code or line.product_id.name or '' if line.cost_line_id: res[line.id] += ' - ' + line.cost_line_id.name return res _columns = { 'name': fields.function(_get_name, type='char', string='Description', store=True), 'cost_id': fields.many2one('stock.landed.cost', 'Landed Cost', required=True, ondelete='cascade'), 'cost_line_id': fields.many2one('stock.landed.cost.lines', 'Cost Line', readonly=True), 'move_id': fields.many2one('stock.move', 'Stock Move', readonly=True), 'product_id': fields.many2one('product.product', 'Product', required=True), 'quantity': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True), 'weight': fields.float('Weight', digits_compute=dp.get_precision('Product Unit of Measure')), 'volume': fields.float('Volume', digits_compute=dp.get_precision('Product Unit of Measure')), 'former_cost': fields.float('Former Cost', digits_compute=dp.get_precision('Product Price')), 'former_cost_per_unit': fields.function(_amount_final, multi='cost', string='Former Cost(Per Unit)', type='float', store=True, digits=0), 'additional_landed_cost': fields.float('Additional Landed Cost', digits_compute=dp.get_precision('Product Price')), 'final_cost': fields.function(_amount_final, multi='cost', string='Final Cost', type='float', store=True, digits=0), } _defaults = { 'quantity': 1.0, 'weight': 1.0, 'volume': 1.0, }
class MassMailingList(osv.Model): """Model of a contact list. """ _name = 'mail.mass_mailing.list' _order = 'name' _description = 'Mailing List' def _get_contact_nbr(self, cr, uid, ids, name, arg, context=None): result = dict.fromkeys(ids, 0) Contacts = self.pool.get('mail.mass_mailing.contact') for group in Contacts.read_group(cr, uid, [('list_id', 'in', ids), ('opt_out', '!=', True)], ['list_id'], ['list_id'], context=context): result[group['list_id'][0]] = group['list_id_count'] return result _columns = { 'name': fields.char('Mailing List', required=True), 'active': fields.boolean('Active'), 'create_date': fields.datetime('Creation Date'), 'contact_nbr': fields.function( _get_contact_nbr, type='integer', string='Number of Contacts', ), 'popup_content': fields.html("Website Popup Content", translate=True, required=True, sanitize=False), 'popup_redirect_url': fields.char("Website Popup Redirect URL"), } def _get_default_popup_content(self, cr, uid, context=None): return """<div class="modal-header text-center"> <h3 class="modal-title mt8">eCore Presents</h3> </div> <div class="o_popup_message"> <font>7</font> <strong>Business Hacks</strong> <span> to<br/>boost your marketing</span> </div> <p class="o_message_paragraph">Join our Marketing newsletter and get <strong>this white paper instantly</strong></p>""" _defaults = { 'active': True, 'popup_content': _get_default_popup_content, 'popup_redirect_url': '/', }
class product_product(osv.Model): _inherit = 'product.product' def _rules_count(self, cr, uid, ids, field_name, arg, context=None): Analytic = self.pool['account.analytic.default'] return { product_id: Analytic.search_count(cr, uid, [('product_id', '=', product_id)], context=context) for product_id in ids } _columns = { 'rules_count': fields.function(_rules_count, string='# Analytic Rules', type='integer'), }
class TestFunctionCounter(osv.Model): _name = 'test_old_api.function_counter' def _compute_cnt(self, cr, uid, ids, fname, arg, context=None): res = {} for cnt in self.browse(cr, uid, ids, context=context): res[cnt.id] = cnt.access and cnt.cnt + 1 or 0 return res _columns = { 'access': fields.datetime('Datetime Field'), 'cnt': fields.function( _compute_cnt, type='integer', string='Function Field', store=True), }
class res_partner(osv.osv): def _issue_count(self, cr, uid, ids, field_name, arg, context=None): Issue = self.pool['project.issue'] return { partner_id: Issue.search_count(cr, uid, [('partner_id', '=', partner_id)]) for partner_id in ids } """ Inherits partner and adds Issue information in the partner form """ _inherit = 'res.partner' _columns = { 'issue_count': fields.function(_issue_count, string='# Issues', type='integer'), }
class stock_picking(osv.osv): _inherit = 'stock.picking' def _claim_count_out(self, cr, uid, ids, field_name, arg, context=None): Claim = self.pool['crm.claim'] return { id: Claim.search_count(cr, uid, [('ref', '=', ('stock.picking,' + str(ids[0])))], context=context) for id in ids } _columns = { 'claim_count_out': fields.function(_claim_count_out, string='Claims', type='integer'), }
class res_partner(osv.osv): _inherit = 'res.partner' def _claim_count(self, cr, uid, ids, field_name, arg, context=None): Claim = self.pool['crm.claim'] return { partner_id: Claim.search_count(cr, uid, [('partner_id', '=', partner_id)], context=context) for partner_id in ids } _columns = { 'claim_count': fields.function(_claim_count, string='# Claims', type='integer'), }
class sale_order_line(osv.osv): _inherit = "sale.order.line" @api.multi @api.onchange('product_id', 'product_uom') def product_id_change_margin(self): for line in self: if line.order_id.pricelist_id: frm_cur = self.env.user.company_id.currency_id to_cur = line.order_id.pricelist_id.currency_id purchase_price = line.product_id.standard_price if line.product_uom != line.product_id.uom_id: purchase_price = self.env['product.uom']._compute_price( line.product_id.uom_id.id, purchase_price, to_uom_id=line.product_uom.id) ctx = self.env.context.copy() ctx['date'] = line.order_id.date_order price = frm_cur.with_context(ctx).compute(purchase_price, to_cur, round=False) line.purchase_price = price def _product_margin(self, cr, uid, ids, field_name, arg, context=None): cur_obj = self.pool.get('res.currency') res = {} for line in self.browse(cr, uid, ids, context=context): cur = line.order_id.pricelist_id.currency_id res[line.id] = 0 if line.product_id: tmp_margin = line.price_subtotal - ( (line.purchase_price or line.product_id.standard_price) * line.product_uom_qty) res[line.id] = cur_obj.round(cr, uid, cur, tmp_margin) return res _columns = { 'margin': fields.function(_product_margin, string='Margin', digits_compute=dp.get_precision('Product Price'), store=True), 'purchase_price': fields.float('Cost', digits_compute=dp.get_precision('Product Price')) }
class ir_attachment(osv.osv): _inherit = "ir.attachment" def _local_url_get(self, cr, uid, ids, name, arg, context=None): result = {} for attach in self.browse(cr, uid, ids, context=context): if attach.url: result[attach.id] = attach.url else: result[attach.id] = '/web/image/%s?unique=%s' % ( attach.id, attach.checksum) return result _columns = { 'local_url': fields.function(_local_url_get, string="Attachment URL", type='char'), }
class res_partner(osv.osv): def _task_count(self, cr, uid, ids, field_name, arg, context=None): Task = self.pool['project.task'] return { partner_id: Task.search_count(cr, uid, [('partner_id', '=', partner_id)], context=context) for partner_id in ids } """ Inherits partner and adds Tasks information in the partner form """ _inherit = 'res.partner' _columns = { 'task_ids': fields.one2many('project.task', 'partner_id', 'Tasks'), 'task_count': fields.function(_task_count, string='# Tasks', type='integer'), }
class groups_implied(osv.osv): _inherit = 'res.groups' def _get_trans_implied(self, cr, uid, ids, field, arg, context=None): "computes the transitive closure of relation implied_ids" memo = {} # use a memo for performance and cycle avoidance def computed_set(g): if g not in memo: memo[g] = cset(g.implied_ids) for h in g.implied_ids: computed_set(h).subsetof(memo[g]) return memo[g] res = {} for g in self.browse(cr, SUPERUSER_ID, ids, context): res[g.id] = map(int, computed_set(g)) return res _columns = { 'implied_ids': fields.many2many('res.groups', 'res_groups_implied_rel', 'gid', 'hid', string='Inherits', help='Users of this group automatically inherit those groups'), 'trans_implied_ids': fields.function(_get_trans_implied, type='many2many', relation='res.groups', string='Transitively inherits'), } def create(self, cr, uid, values, context=None): users = values.pop('users', None) gid = super(groups_implied, self).create(cr, uid, values, context) if users: # delegate addition of users to add implied groups self.write(cr, uid, [gid], {'users': users}, context) return gid def write(self, cr, uid, ids, values, context=None): res = super(groups_implied, self).write(cr, uid, ids, values, context) if values.get('users') or values.get('implied_ids'): # add all implied groups (to all users of each group) for g in self.browse(cr, uid, ids, context=context): gids = map(int, g.trans_implied_ids) vals = {'users': [(4, u.id) for u in g.users]} super(groups_implied, self).write(cr, uid, gids, vals, context) return res
class TestFunctionNoInfiniteRecursion(osv.Model): _name = 'test_old_api.function_noinfiniterecursion' def _compute_f1(self, cr, uid, ids, fname, arg, context=None): res = {} for tf in self.browse(cr, uid, ids, context=context): res[tf.id] = 'create' in tf.f0 and 'create' or 'write' cntobj = self.pool['test_old_api.function_counter'] cnt_id = self.pool['ir.model.data'].xmlid_to_res_id( cr, uid, 'test_new_api.c1') cntobj.write( cr, uid, cnt_id, {'access': datetime.datetime.now()}, context=context) return res _columns = { 'f0': fields.char('Char Field'), 'f1': fields.function( _compute_f1, type='char', string='Function Field', store=True), }
class project(osv.Model): _inherit = "project.project" def _get_alias_models(self, cr, uid, context=None): res = super(project, self)._get_alias_models(cr, uid, context=context) res.append(("project.issue", "Issues")) return res def _issue_count(self, cr, uid, ids, field_name, arg, context=None): Issue = self.pool['project.issue'] return { project_id: Issue.search_count(cr, uid, [('project_id', '=', project_id), ('stage_id.fold', '=', False)], context=context) for project_id in ids } _columns = { 'issue_count': fields.function( _issue_count, type='integer', string="Issues", ), 'issue_ids': fields.one2many('project.issue', 'project_id', string="Issues", domain=[('stage_id.fold', '=', False)]), } @api.multi def write(self, vals): res = super(project, self).write(vals) if 'active' in vals: # archiving/unarchiving a project does it on its issues, too issues = self.with_context(active_test=False).mapped('issue_ids') issues.write({'active': vals['active']}) return res
class website_pricelist(osv.Model): _name = 'website_pricelist' _description = 'Website Pricelist' def _get_display_name(self, cr, uid, ids, name, arg, context=None): result = {} for o in self.browse(cr, uid, ids, context=context): result[o.id] = _("Website Pricelist for %s") % o.pricelist_id.name return result _columns = { 'name': fields.function(_get_display_name, string='Pricelist Name', type="char"), 'website_id': fields.many2one('website', string="Website", required=True), 'selectable': fields.boolean('Selectable', help="Allow the end user to choose this price list"), 'pricelist_id': fields.many2one('product.pricelist', string='Pricelist'), 'country_group_ids': fields.many2many('res.country.group', 'res_country_group_website_pricelist_rel', 'website_pricelist_id', 'res_country_group_id', string='Country Groups'), } def clear_cache(self): # website._get_pl() is cached to avoid to recompute at each request the # list of available pricelists. So, we need to invalidate the cache when # we change the config of website price list to force to recompute. website = self.pool['website'] website._get_pl.clear_cache(website) def create(self, cr, uid, data, context=None): res = super(website_pricelist, self).create(cr, uid, data, context=context) self.clear_cache() return res def write(self, cr, uid, ids, data, context=None): res = super(website_pricelist, self).write(cr, uid, ids, data, context=context) self.clear_cache() return res def unlink(self, cr, uid, ids, context=None): res = super(website_pricelist, self).unlink(cr, uid, ids, context=context) self.clear_cache() return res
class mrp_repair_fee(osv.osv, ProductChangeMixin): _name = 'mrp.repair.fee' _description = 'Repair Fees Line' def _amount_line(self, cr, uid, ids, field_name, arg, context=None): """ Calculates amount. @param field_name: Name of field. @param arg: Argument @return: Dictionary of values. """ res = {} tax_obj = self.pool.get('account.tax') cur_obj = self.pool.get('res.currency') for line in self.browse(cr, uid, ids, context=context): if line.to_invoice: cur = line.repair_id.pricelist_id.currency_id taxes = tax_obj.compute_all(cr, uid, line.tax_id, line.price_unit, cur.id, line.product_uom_qty, line.product_id.id, line.repair_id.partner_id.id) res[line.id] = taxes['total_included'] else: res[line.id] = 0 return res _columns = { 'repair_id': fields.many2one('mrp.repair', 'Repair Order Reference', required=True, ondelete='cascade', select=True), 'name': fields.char('Description', select=True, required=True), 'product_id': fields.many2one('product.product', 'Product'), 'product_uom_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True), 'price_unit': fields.float('Unit Price', required=True), 'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True), 'price_subtotal': fields.function(_amount_line, string='Subtotal', digits=0), 'tax_id': fields.many2many('account.tax', 'repair_fee_line_tax', 'repair_fee_line_id', 'tax_id', 'Taxes'), 'invoice_line_id': fields.many2one('account.invoice.line', 'Invoice Line', readonly=True, copy=False), 'to_invoice': fields.boolean('To Invoice'), 'invoiced': fields.boolean('Invoiced', readonly=True, copy=False), } _defaults = { 'to_invoice': lambda *a: True, }
class res_partner(osv.osv): _inherit = 'res.partner' def _sale_order_count(self, cr, uid, ids, field_name, arg, context=None): res = dict(map(lambda x: (x, 0), ids)) # The current user may not have access rights for sale orders try: for partner in self.browse(cr, uid, ids, context): res[partner.id] = len(partner.sale_order_ids) + len( partner.mapped('child_ids.sale_order_ids')) except: pass return res _columns = { 'sale_order_count': fields.function(_sale_order_count, string='# of Sales Order', type='integer'), 'sale_order_ids': fields.one2many('sale.order', 'partner_id', 'Sales Order') }
class hr_employee(osv.osv): ''' Employee ''' _inherit = 'hr.employee' _description = 'Employee' def _timesheet_count(self, cr, uid, ids, field_name, arg, context=None): Sheet = self.pool['hr_timesheet_sheet.sheet'] return { employee_id: Sheet.search_count(cr, uid, [('employee_id', '=', employee_id)], context=context) for employee_id in ids } _columns = { 'timesheet_count': fields.function(_timesheet_count, type='integer', string='Timesheets'), }
class product_template(osv.Model): _inherit = 'product.template' def _rules_count(self, cr, uid, ids, field_name, arg, context=None): Analytic = self.pool['account.analytic.default'] res = {} for product_tmpl_id in self.browse(cr, uid, ids, context=context): res[product_tmpl_id.id] = sum([p.rules_count for p in product_tmpl_id.product_variant_ids]) return res _columns = { 'rules_count': fields.function(_rules_count, string='# Analytic Rules', type='integer'), } def action_view_rules(self, cr, uid, ids, context=None): products = self._get_products(cr, uid, ids, context=context) result = self._get_act_window_dict(cr, uid, 'account_analytic_default.action_product_default_list', context=context) result['domain'] = "[('product_id','in',[" + ','.join(map(str, products)) + "])]" # Remove context so it is not going to filter on product_id with active_id of template result['context'] = "{}" return result
class ResCompany(osv.Model): _inherit = "res.company" def _get_paypal_account(self, cr, uid, ids, name, arg, context=None): Acquirer = self.pool['payment.acquirer'] company_id = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id.id paypal_ids = Acquirer.search(cr, uid, [ ('website_published', '=', True), ('name', 'ilike', 'paypal'), ('company_id', '=', company_id), ], limit=1, context=context) if paypal_ids: paypal = Acquirer.browse(cr, uid, paypal_ids[0], context=context) return dict.fromkeys(ids, paypal.paypal_email_account) return dict.fromkeys(ids, False) def _set_paypal_account(self, cr, uid, id, name, value, arg, context=None): Acquirer = self.pool['payment.acquirer'] company_id = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id.id paypal_account = self.browse(cr, uid, id, context=context).paypal_account paypal_ids = Acquirer.search(cr, uid, [ ('website_published', '=', True), ('paypal_email_account', '=', paypal_account), ('company_id', '=', company_id), ], context=context) if paypal_ids: Acquirer.write(cr, uid, paypal_ids, {'paypal_email_account': value}, context=context) return True _columns = { 'paypal_account': fields.function( _get_paypal_account, fnct_inv=_set_paypal_account, nodrop=True, type='char', string='Paypal Account', help="Paypal username (usually email) for receiving online payments." ), }
class sale_order(osv.osv): _inherit = "sale.order" def _product_margin(self, cr, uid, ids, field_name, arg, context=None): result = {} for sale in self.browse(cr, uid, ids, context=context): result[sale.id] = 0.0 for line in sale.order_line: if line.state == 'cancel': continue result[sale.id] += line.margin or 0.0 return result def _get_order(self, cr, uid, ids, context=None): result = {} for line in self.pool.get('sale.order.line').browse(cr, uid, ids, context=context): result[line.order_id.id] = True return result.keys() _columns = { 'margin': fields.function( _product_margin, string='Margin', help= "It gives profitability by calculating the difference between the Unit Price and the cost.", store={ 'sale.order.line': (_get_order, ['margin', 'purchase_price'], 20), 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 20), }, digits_compute=dp.get_precision('Product Price')), }
class product_category(osv.osv): _inherit = 'product.category' def calculate_total_routes(self, cr, uid, ids, name, args, context=None): res = {} for categ in self.browse(cr, uid, ids, context=context): categ2 = categ routes = [x.id for x in categ.route_ids] while categ2.parent_id: categ2 = categ2.parent_id routes += [x.id for x in categ2.route_ids] res[categ.id] = routes return res _columns = { 'route_ids': fields.many2many('stock.location.route', 'stock_location_route_categ', 'categ_id', 'route_id', 'Routes', domain="[('product_categ_selectable', '=', True)]"), 'removal_strategy_id': fields.many2one( 'product.removal', 'Force Removal Strategy', help= "Set a specific removal strategy that will be used regardless of the source location for this product category" ), 'total_route_ids': fields.function(calculate_total_routes, relation='stock.location.route', type='many2many', string='Total routes', readonly=True), }
class event_ticket(models.Model): _name = 'event.event.ticket' _description = 'Event Ticket' name = fields.Char('Name', required=True, translate=True) event_id = fields.Many2one('event.event', "Event", required=True, ondelete='cascade') product_id = fields.Many2one( 'product.product', 'Product', required=True, domain=[("event_type_id", "!=", False)], default=lambda self: self._default_product_id()) registration_ids = fields.One2many('event.registration', 'event_ticket_id', 'Registrations') price = fields.Float('Price', digits=dp.get_precision('Product Price')) deadline = fields.Date("Sales End") is_expired = fields.Boolean('Is Expired', compute='_is_expired') @api.model def _default_product_id(self): try: product = self.env['ir.model.data'].get_object( 'event_sale', 'product_product_event') return product.id except ValueError: return False @api.one @api.depends('deadline') def _is_expired(self): if self.deadline: current_date = fields.Date.context_today( self.with_context({'tz': self.event_id.date_tz})) self.is_expired = self.deadline < current_date else: self.is_expired = False # FIXME non-stored fields wont ends up in _columns (and thus _all_columns), which forbid them # to be used in qweb views. Waiting a fix, we create an old function field directly. """ price_reduce = fields.Float("Price Reduce", compute="_get_price_reduce", store=False, digits=dp.get_precision('Product Price')) @api.one @api.depends('price', 'product_id.lst_price', 'product_id.price') def _get_price_reduce(self): product = self.product_id discount = product.lst_price and (product.lst_price - product.price) / product.lst_price or 0.0 self.price_reduce = (1.0 - discount) * self.price """ def _get_price_reduce(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, 0.0) for ticket in self.browse(cr, uid, ids, context=context): product = ticket.product_id discount = product.lst_price and ( product.lst_price - product.price) / product.lst_price or 0.0 res[ticket.id] = (1.0 - discount) * ticket.price return res _columns = { 'price_reduce': old_fields.function(_get_price_reduce, type='float', string='Price Reduce', digits_compute=dp.get_precision('Product Price')), } # seats fields seats_availability = fields.Selection([('limited', 'Limited'), ('unlimited', 'Unlimited')], 'Available Seat', required=True, store=True, compute='_compute_seats', default="limited") seats_max = fields.Integer( 'Maximum Available Seats', help= "Define the number of available tickets. If you have too much registrations you will " "not be able to sell tickets anymore. Set 0 to ignore this rule set as unlimited." ) seats_reserved = fields.Integer(string='Reserved Seats', compute='_compute_seats', store=True) seats_available = fields.Integer(string='Available Seats', compute='_compute_seats', store=True) seats_unconfirmed = fields.Integer(string='Unconfirmed Seat Reservations', compute='_compute_seats', store=True) seats_used = fields.Integer(compute='_compute_seats', store=True) @api.multi @api.depends('seats_max', 'registration_ids.state') def _compute_seats(self): """ Determine reserved, available, reserved but unconfirmed and used seats. """ # initialize fields to 0 + compute seats availability for ticket in self: ticket.seats_availability = 'unlimited' if ticket.seats_max == 0 else 'limited' ticket.seats_unconfirmed = ticket.seats_reserved = ticket.seats_used = ticket.seats_available = 0 # aggregate registrations by ticket and by state if self.ids: state_field = { 'draft': 'seats_unconfirmed', 'open': 'seats_reserved', 'done': 'seats_used', } query = """ SELECT event_ticket_id, state, count(event_id) FROM event_registration WHERE event_ticket_id IN %s AND state IN ('draft', 'open', 'done') GROUP BY event_ticket_id, state """ self._cr.execute(query, (tuple(self.ids), )) for event_ticket_id, state, num in self._cr.fetchall(): ticket = self.browse(event_ticket_id) ticket[state_field[state]] += num # compute seats_available for ticket in self: if ticket.seats_max > 0: ticket.seats_available = ticket.seats_max - ( ticket.seats_reserved + ticket.seats_used) @api.one @api.constrains('registration_ids', 'seats_max') def _check_seats_limit(self): if self.seats_max and self.seats_available < 0: raise UserError(_('No more available seats for the ticket')) @api.onchange('product_id') def onchange_product_id(self): price = self.product_id.list_price if self.product_id else 0 return {'value': {'price': price}}
('float', fields.float()), ('decimal', fields.float(digits=(16, 3))), ('string.bounded', fields.char('unknown', size=16)), ('string.required', fields.char('unknown', size=None, required=True)), ('string', fields.char('unknown', size=None)), ('date', fields.date()), ('datetime', fields.datetime()), ('text', fields.text()), ('selection', fields.selection([(1, "Foo"), (2, "Bar"), (3, "Qux"), (4, '')])), # here use size=-1 to store the values as integers instead of strings ('selection.function', fields.selection(selection_fn, size=-1)), # just relate to an integer ('many2one', fields.many2one('export.integer')), ('one2many', fields.one2many('export.one2many.child', 'parent_id')), ('many2many', fields.many2many('export.many2many.other')), ('function', fields.function(function_fn, fnct_inv=function_fn_write, type="integer")), # related: specialization of fields.function, should work the same way # TODO: reference ] for name, field in models: class NewModel(orm.Model): _name = 'export.%s' % name _columns = { 'const': fields.integer(), 'value': field, } _defaults = { 'const': 4, }