how to use functional field in record rule? - odoo

I am trying to achieve that all the users that are Hr managers should be allowed to see the records.
I have created a Functional Field:
def list_HRM(self, cr, uid, ids, field_name, arg, context):
attribute = {}
hr_managers = self.pool.get('hr.employee').search(cr, uid, ['&', ('department_id.name', '=', 'Human Resources'), ('manager', '=', True)], context=context)
hr_managers_uid = []
for record in hr_managers:
hr_managers_uid.append(self.pool.get('hr.employee').browse(cr, uid, record, context=context).user_id.id)
record = self.browse(cr, uid, ids)[0]
attribute[record.id] = str(uid in hr_managers_uid or uid==1)
return attribute
_columns={
'hr_managers_func' : fields.function(list_HRM, type='char', method=True, string='List of HR Managers'),
'always_true':fields.boolean()
}
_defaults={
'always_true':True
}
In .xml file:
<field name="always_true" invisible="1"/>
<field name="hr_managers_func" invisible="1"/>
In Record Rule:
['&','|',('state','=','hod_depart'),('state','=','hr_review'),('always_true','=',eval(hr_managers_func))]
I used field 'always_true' because of the record rule condition format i.e.
[('field_name','operator',values)].
I thought that rule will evaluate the functional field using eval
but unfortunately eval is not working on the record rule ,
I am getting this error:
NameError: name 'eval' is not defined
I could not think of more than this.
I saw few forum somewhat similar to my problem, they were using the related field to avoid the functional field in the record, but here I have to check whether the current user belong to hr managers or not .
I have tried explaining this in the best possible way, Looking forward for some reply.

To restrict on a function field, you need to define a fnct_search. The functional field per se becomes a dummy.
In your model:
def _my_functional_field_search(self, cr, uid, obj, name, args, context=None):
list_of_ids = [...]
return [('id', 'in', list_of_ids)]
_columns = {
'my_functional_field': fields.function(
lambda **x: True,
fnct_search=_my_functional_field_search,
type='boolean',
method=True,
),
}
And then in your security XML file:
<record id="your_rule_id" model="ir.rule">
<field name="name">Your Rule Name</field>
<field name="model_id" ref="model_the_model" />
<field name="groups" eval="[(4, ref('group_affected_group'))]" />
<field name="domain_force">[('my_functional_field', '=', True)]</field>
</record>

Related

Sequencing in odoo 10

I am trying to create a sequence in odoo here is my xml file
<record model="ir.sequence" id="connection_sequence_id">
<field name="name">New Connections Sequence</field>
<field name="code">ftth.connection</field>
<field name="prefix">FTTH</field>
<field name="padding">6</field>
<field name="company_id" eval="False" />
</record>
I have created a field for it in my .py file
my_seq = fields.Char(string="sequence", default=lambda self: _('New'))
and overiddeen the create function by using the following code
#api.model
def create(self, vals):
if vals:
vals['my_seq'] = self.env['ir.sequence'].next_by_code('ftth.connection') or _('New')
result = super(NewConnections, self).create(vals)
return result
but my code is not generating a sequence instead it gives ftth.connection.(sequence number).what might be wrong with my code.please assist
use super to customize your create function, this an example:
#api.model
def create(self, vals):
if vals:
seq = self.env['ir.sequence']
vals['my_seq'] = seq.next_by_code('ftth.connection') or _('New')
return super(ObjectName, self).create(values)

Odoo 10: show field of model "sale.order" in form view of "account.invoice"

I usually create a new Database Structure Field by using the Debugging Mode, then Edit FormView and writing e.g. <field name="x_delivery_date"/>. Also I can show it later on the printed report like this:
<div name="x_delivery_date" t-if="doc.x_delivery_date">
<strong>Delivery Date:</strong>
<p t-field="doc.x_delivery_date"/>
</div>
But how do I display a field (commitment_date), which is available in the model (sale.order) in another models formview (account.invoice)? I guess that I have to use object relations or related field, but I don't know how. I hope somebody can help me. Many thanks in advance.
You can use related fields for that. You have to add two fields to account.invoice to do it.
class AccountInvoice(models.Model):
_inherit = "account.invoice"
order_id = fields.Many2one('sale.order', 'Related_order')
commitment_date = fields.Date(related='order_id.commitment_date')
Then you can use the commitment_date fields in account.invoice forms. The value of the field in sale.order will be reflected on the form right away. But be aware that changing the value of that field will change the value of that field on the sale.order as well.
EDIT
For reports just use the field like it is a regular field of account.invoice (so doc.commitment_date)
First you need to add a many2one field in account.invoice
class account_invoice(osv.osv):
_inherit = "account.invoice"
_columns = {
'source_id':fields.many2one('sale.order','Source')
}
Then inherit the _prepare_invoice function in sale_order. In this function you are going to pass the sale order id as source id to the account.invoice
class sale_order(osv.osv):
_inherit = "sale.order"
def _prepare_invoice(self, cr, uid, order, lines, context=None):
if context is None:
context = {}
journal_id = self.pool['account.invoice'].default_get(cr, uid, ['journal_id'], context=context)['journal_id']
if not journal_id:
raise osv.except_osv(_('Error!'),
_('Please define sales journal for this company: "%s" (id:%d).') % (order.company_id.name, order.company_id.id))
invoice_vals = {
'name': order.client_order_ref or '',
'origin': order.name,
'type': 'out_invoice',
#Sale order id as source_id
'source_id':order.id,
'reference': order.client_order_ref or order.name,
'account_id': order.partner_invoice_id.property_account_receivable.id,
'partner_id': order.partner_invoice_id.id,
'journal_id': journal_id,
'invoice_line': [(6, 0, lines)],
'currency_id': order.pricelist_id.currency_id.id,
'comment': order.note,
'payment_term': order.payment_term and order.payment_term.id or False,
'fiscal_position': order.fiscal_position.id or order.partner_invoice_id.property_account_position.id,
'date_invoice': context.get('date_invoice', False),
'company_id': order.company_id.id,
'user_id': order.user_id and order.user_id.id or False,
'section_id' : order.section_id.id
}
invoice_vals.update(self._inv_get(cr, uid, order, context=context))
return invoice_vals
Add this in View file
<record id="invoice_form" model="ir.ui.view">
<field name="name">account.invoice.form</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<xpath expr="//field[#name='date_invoice']" position="after">
<field name="source_id"/>
</xpath>
</field>
</record>
Now add this in your report file
<div name="x_delivery_date" t-if="doc.x_delivery_date">
<strong>Delivery Date:</strong>
<p t-field="doc.x_delivery_date"/>
<p t-field="doc.source_id.commitment_date"/>
</div>

How to store default entered value in custom field of quantity on Hand.?

Need to store default value on qty in M.sqr and square meter like quantity on hand showing default entered value.
when i click on update button of quantity on Hand from product inventory page
then it should show me a previous entered value.
class stock_change_product_qty(osv.osv):
_inherit = 'stock.change.product.qty'
_columns = {
'new_quantity' : fields.float('Qty in Boxes'),
'squ_meter': fields.related('product_id','squ_meter', type='float', relation='product.product', string='Square Meter'),
'qty_char': fields.float('Qty in M.sqr', compute='_compute_qty_char'),
}
#api.depends('new_quantity', 'squ_meter')
def _compute_qty_char(self):
for record in self:
record.qty_char = record.new_quantity * record.squ_meter
view.xml
<field name="name">update_product_quantity inherit</field>
<field name="model">stock.change.product.qty</field>
<field name="inherit_id" ref="stock.view_change_product_quantity"/>
<field name="arch" type="xml">
<xpath expr="//field[#name='new_quantity']" position="attributes">
<attribute name="string">Qty in Boxes</attribute>
</xpath>
<xpath expr="//field[#name='new_quantity']" position="replace">
<field name="new_quantity"/>
<field name="squ_meter"/>
<field name="qty_char"/>
</xpath>
</field>
</record>
A solution is to use a function as default value for your field:
odoo V8
from openerp import api, fields, models
class stock_change_product_qty(models.Model):
_inherit = 'stock.change.product.qty'
new_quantity = fields.Float(string='Qty in Boxes', default=1.0),
squ_meter = fields.Float(related='product_id.squ_meter', string='Square Meter', default=1.0),
qty_char = fields.Float('Qty in M.sqr', compute='_compute_qty_char'),
}
#api.one
#api.depends('new_quantity', 'squ_meter')
def _compute_qty_char(self):
for record in self:
record.qty_char = record.new_quantity * record.squ_meter
odoo V7
def _your_function(self, cr, uid, context=None):
your code here
...
...
...
return field_value
_defaults = {
'your_field' : _your_function,
}
#api.onchange
This decorator will trigger the call to the decorated function if any of the fields specified in the decorator is changed in the form:
#api.onchange('fieldx')
def do_stuff(self):
if self.fieldx == x:
self.fieldy = 'toto'
In previous sample self corresponds to the record currently edited on the form. When in on_change context all work is done in the cache. So you can alter RecordSet inside your function without being worried about altering database. That’s the main difference with #api.depends
At function return, differences between the cache and the RecordSet will be returned to the form.

How to autofill employee details when employee name is selected in odoo?

How to get the details of employee when employee name is selected in odoo.
I have made a many2one field relating with hr.employee. but i am not able to get the results
.py code
class mom_person(osv.Model):
_name = 'mom.person'
_columns = {
'emp_i' : fields.many2one('hr.employee','Attendees'),
'ename_id' : fields.many2one('mom.meeting','Attend Person'),
'depat':fields.char('Department'),
'wk_mail':fields.char('Mail'),
'wk_cnt':fields.char('Contact'),
}
def get_emp_det(self, cr, uid, ids, emp_i, context=None):
val = {}
emp_id = self.pool.get('hr.employee')
if emp_i:
for rec in emp_id.browse(cr,uid,emp_i,context=context):
val = {
'depat': rec.department_id,
'wk_mail':rec.work_email,
'wk_cnt':rec.work_phone,
}
return val
mom_person()
and xml code
<tree string="Employee name" editable="bottom">
<field name="emp_i" onchange="get_emp_det(emp_i)"/>
<field name="depat"/>
<field name="wk_mail"/>
<field name="wk_cnt"/>
</tree>
/field>
You must have to change the onchanage method in your .py file try do to given below :
def get_emp_det(self, cr, uid, ids, emp_i, context=None):
v={}
if emp_i:
employee = self.pool.get('hr.employee').browse(cr, uid, emp_i, context=context)
if employee.department_id.id:
v['depat'] = employee.department_id and employee.department_id.id or False
if employee.work_email:
v['wk_mail'] = employee.work_email
if employee.work_phone:
v['wk_cnt'] = employee.work_phone
return {'value': v}
You can try above onchange and restart the server and see the result
I hope this should helpful for you ..:)

Autofill some fields Openerp

Hi I am new to OpenERP7/Odoo7 and not really getting how to do this.
I have a existing records in my custom product module and I want to retrieve that record by entering only to my prodcode fields and want to autofill some fields.
I have been reading a lot on the internet, Odoo forums, but cannot find the answer or I just don't understand it. I already have post with regards to my problem
So if is there someone could give me an answer on how to achieve this, or direct me to a easy to understand explanation.
That would be great.
Here is I have done already
PYTHON---
class test_product(osv.Model):
_name = "test.product"
def name_change(self, cr, uid, ids, test_prodcode_id, prodname, desc, price, context=None):
return {
'value': {
'prodname': 'Plastic Ware',
'desc': 'Affordable Plastic Ware',
'price': 100.00,
}
}
_columns = {
'test_prodcode_id': fields.many2one('test.prodcode', 'Code'),
'prodname': fields.char('Name', size=32),
'desc': fields.char('Description', size=32),
'price': fields.float('Price',),
}
class test_prodcode(osv.Model):
_name = "test.prodcode"
_columns = {
'name': fields.char('Product Code', size=32),
}
XML----
<record id="test_product_form_view" model="ir.ui.view">
<field name="name">test.product.form.vew</field>
<field name="model">test.product</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Product" version="7.0">
<sheet>
<field name="test_prodcode_id" on_change="name_change(test_prodcode_id,prodname,desc,price)"/>
<field name="prodname"/>
<field name="desc"/>
<field name="price"/>
</sheet>
</form>
</field>
</record>
Yeah, I've had this problem too.
I've got the solution. Auto fill can be achieved by doing
_defaults = {}
, or, as in your example, by doing
class test_product(osv.Model):
_columns = {
'test_prodcode_id': fields.many2one('test.prodcode', 'Code'),
'prodname': fields.char('Name', size=32),
'desc': fields.char('Description', size=32),
'price': fields.float('Price',),
}
_defaults: {
'test_prodcode_id' : 'defaults_prodcode',
}
You can also assign a function that return the value of the defaults.
I have solution but it is not as exactly as you want but you can do like
this also.
You can use related for auto fill your other fields. Suppose you set
product_id it will auto fill product_name, desc and price regarding to
your product_id.
You can also see Example here :
https://stackoverflow.com/a/42453539/5161074