I'm creating a log entry within a server action in Odoo 10. This is the server action Python code:
if record:
env['ir.logging'].create({
'type': 'server',
'name': 'test',
'level': record._name,
'path': 'test',
'line': 'test,
'func': '#',
'message': '#'
})
The line value for level of record._name gets me the name of the current model as a string, for example, product.product, or sale.order.
However, I don't think the _name attribute is not meant to be part of the public API. Does anyone know of a public way to retrieve the name of the model?
The model variable is also available in the server action, which returns product.product(). However, want product.product, without the parenthesis. I realize I could just use a string method to trim off the (), but I'm wondering if there is an intended way to get just the name of the model as a string.
Any ideas?
I don't see another way. _name is "private" and you could use __str__, which will give you the model name and the ids of the current RecordSet. The regex for odoo's model names is r'^[a-z0-9_.]+$', so i suggest, what you've already known: trim off everything at the end.
Related
How can I restrict the write permissions for a field to a specific group ?
I want to check if a user is in a specific group with id 46. If the user is in this group, he should be allowed to write in this field. If he is not in this group, he should not be allowed to write.
The field is a custom field, editing the domain with the studio app I think I should avoid.
My field:
<field name="customer_codename" placeholder="Codename" attrs="{'invisible':['|',('customer_rank','=', 0),('is_company','=', False)]}"/>
I tried the following, but it did not work:
I created a new field using the studio app. Field type is boolean.
In the advanced properties I wanted to define the compute for the field. In dependencies I gave "user_id" and in the compute field I gave
for record in self:
user_id.has_group('__export__.res_groups_46_eff9dc52')
The boolean field should be set to true if the user is in a certain group.
Not sure if I can give you the best answer there is.
But for me, I'd personally create a Boolean field in the view's associated model, with its default field a lambda function checking if the user belongs to the groups you mentioned.
Assuming groups_id is the name of the user groups in model res.users, we have:
class ResUsers(models.Model):
_inherit = "res.users"
can_write_codename = fields.Boolean(default=lambda self: self.groups_id in ("model_name.group_name"))
Then in your xml file, you can include can_write_codename inside attrs, like this:
<field name="customer_codename" placeholder="Codename" attrs="{'invisible':['|',('customer_rank','=', 0),('is_company','=', False)], 'readonly': [('can_write_codename', '=', 'True')]}"}"/>
I have a sequelize query that I would like to save in a database and then execute on demand. In order to do this I am first testing how this would work in a variable as a string (because in a database it will be stored as a string):
queryToRun = models.user.findAll({
attributes: [
['name', 'name'],
[Sequelize.literal("COUNT(DISTINCT(user.id))"), "user_count"]
],
group: Sequelize.col("user.name")
})
With this query I would like to use it like so:
Promise.all(queryToRun);
I am successfully able to save the object (object that goes inside findAll with the attributes etc) as a string and then execute, but I can't figure out how to save every part of the query. I want to save the actual "model.user.findAll()"string and evaluate it at a later time.
This is important because I want to define the model that I need to run findAll on and save it in the database.
This is actually fairly simple
Don't use the multiline string it trips up the function call for some reason
Use eval to evaluate the string
Example:
let queryToRun = 'models.project.findAll({})';
Promise.all([eval(queryToRun)]);
I am trying to create a server action via the Odoo UI that will alter the domain of another field in the view. This seems to be a pretty common use-case when dealing with the Odoo source code as you can see in the following documentation:
https://www.odoo.com/documentation/10.0/reference/orm.html#odoo.api.onchange
In those docs, they indicate that if I were in the source code of the model, I can define an onchange method and return a domain, for example, the behavior I'm trying to accomplish in the sale.order.line model would be:
#api.onchange('product_id')
def _onchange_product(self):
return {
'domain': {'route_id': [('id', 'in', x_all_route_ids.ids)]}
}
In other words, when the product of an sales order line changes, update the available options in the route_id field.
Is there any way to accomplish this same thing via a server action created through the UI? I am having trouble figuring out how to return a domain from the Python code.
The notes in the code section say:
# Available variables:
# - time, datetime, dateutil, timezone: Python libraries
# - env: Odoo Environement
# - model: Model of the record on which the action is triggered
# - record: Record on which the action is triggered if there is one, otherwise None
# - records: Records on which the action is triggered if there is one, otherwise None
# - log : log(message), function to log debug information in logging table
# - Warning: Warning Exception to use with raise
# To return an action, assign: action = {...}
I don't see how I can use this to return a domain. Does anybody have any idea?
I have tried setting the python code field to simply:
domain = {'route_id': [('id', 'in', record.x_all_route_ids)]}
But that doesn't work. The route_id list is unchanged.
I got some insight from Odoo technical support and it turns out this is possible. Anything assigned to the action variable will be treated as the return value for the server action.
So you can simply do:
action = {
'domain': {
'route_id': [('id', 'in', record.x_all_route_ids.ids)]
}
}
It is not possible. Only these special on-change methods return values will be evaluated correctly.
I have database field called name. And i have used user.name in my application. Now I have something like salutation which i wanted to append with the name. So what i basically want is when i am accessing name via user.name it should fetch the value from instance method rather then database field.
def name_with_salutation
"#{salutation} #{name}"
end
So when i am accessing name via user.name it should respond with user.name_with_salutation. I have tried alias_method but it shows stack level too deep because name is getting used in name_with_salutation so it got stuck in infinite process.
I am trying this because i do not want to replace name with name_with_salutation throughout the application. This should not apply when i am assigning values user.name = "abc".
Please let me know, How this will be done.
To overwrite an original Model method, you can write a method with same name, and then use read_attribute(:attr) to represent the original attribute value.
Given name attribute exist, to overwrite #name:
def name
"#{salutation} #{read_attribute(:name)}"
end
I really need to add an additional 'state' value on my Sale Order object. Since version 7.0, the 'sale_stock' module does exactly that already. When you try to do the same thing from your own module, your key,value just gets ignored. Is there any other alternative to achieve this?
As I found out, this seems to be an old time issue from two years ago as explained in this thread. A suggested workaround there was to do something like this:
_inherit = 'sale.order'
def __init__(self, pool, cr):
super(sale_order, self)._columns['state'].selection.append(('keyx', 'valuex'))
I found this approach logical, but it resulted in the following error:
`File "/home/nicolas/Eclipse/OpenERP/7.0/src/openerp/osv/orm.py", line 2958, in _auto_init
self._field_create(cr, context=context)
File "/home/nicolas/Eclipse/OpenERP/7.0/src/openerp/osv/orm.py", line 764, in _field_create
ir_model_fields_obj = self.pool.get('ir.model.fields')
AttributeError: 'sale.order' object has no attribute 'pool'`
Should this bug be reported at launchpad or is it an unintended use? What other possible solutions can you suggest? Thanks in advance.
try this
from openerp.osv import osv, fields
class sale_order(osv.osv):
_inherit = 'sale.order'
selection_list = [];#add your selection list here.
_columns = {
'state': fields.selection(selection_list,'State');#add necessary arguments
}
sale_order()
simply inherit the sale.order model and add your state field as it is which define in existing model , add the external state which you are required to add additionaly
for eg:
class sale_order(osv.osv)
_inherit ='sale.order'
_columns = {
'state': fields.selection([
('draft', 'Quotation'),
('waiting_date', 'Waiting Schedule'),
('manual', 'To Invoice'),
('progress', 'In Progress'),
('shipping_except', 'Shipping Exception'),
('invoice_except', 'Invoice Exception'),
('done', 'Done'),
('cancel', 'Cancelled'),
**('key','value')**,
This above would be your newly added selection value sequence dosen't matter.
], 'Order State', readonly=True, help="Gives the state of the quotation or sales order. \nThe exception state is automatically set when a cancel operation occurs in the invoice validation (Invoice Exception) or in the picking list process (Shipping Exception). \nThe 'Waiting Schedule' state is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True),
}
sale_order()
than abouve key value will be your additional selection field and you can set it any where in the squence as per your requirements.
having the same problem, I had a look at the thread, you noticed.
I guess that the problem comes from the fact that our modules and sale_stock are "in conflict" because they modify the same field ('state') in the sale.order object and are not depending of each other.
One solution is to modify your own module and adding 'sale_stock" in the 'depends' list of openerp.py :
depends : ['sale_stock',...]
You can see an example in this module which had another (key,value) in state field : http://bazaar.launchpad.net/~agaplan/agaplan-addons/7.0/files/head:/sale_double_validation/
Hope it helps