Im trying to make an Automated Action, when I create a user also grand access to portal.
My code so far is bind on button Apply to All (see image below):
for rec in records:
for user in rec.user_ids:
user['in_portal'] = True
rec.action_apply()
Apply to All Button Code: <button name="563" type="action" string="Apply to All"/>
How can i modify the code so it run, when I create a user and also grand access to portal?
There are some options, to implement what you need.
Override create() of model res.users and just add users to your desired group(s) after super call.
Create an automated action (Settings/Technical/Automation/Automated Actions)
Model: Users (res.users)
Trigger Condition: On Creation
Action To Do: Update the Record
Data to Write: add one line
Field: Groups (res.users)
Evaluation Type: Python expression
Value: [(4,env.ref('external id of group').id)]
Substitute external id of group with base.group_portal so in your case it should be [(4,env.ref('base.group_portal').id)]
Related
Hello im new in programming with openerp ODOO , well my issue is where i can find the functions of inserting into odoo database , well i created a new field and i want to insert the data of this field into the db
It sounds like as you said, you are just getting started.
I would advise going through the following tutorial for starters.
You need to get an understanding of how Models and Views work in Odoo first and foremost.
Assuming you have added a new field to your model you will need to add this new field to a view for this model.
You will notice that if you have the appropriate permissions you will have an "Edit" and "Save" button (depending on state) on the top left of your views.
These buttons are mapped to functions which can be found on your model.
When you define your model you will notice it inherits models.Model which adds a lot of functionality that you will need for your model. This includes all CRUD operations. You can overide the default function if needed like so
The CREATE METHOD
#api.model
#api.returns('self', lambda rec: rec.id)
def create(self, vals):
# CUSTOM CODE BEFORE RECORD CREATION
rec = super(FocusType, self).create(vals)
# CUSTOM CODE AFTER RECORD CREATION
return rec
THE WRITE METHOD
#api.multi
def write(self, vals):
# CUSTOM CODE BEFORE RECORD WRITE
result = super(FocusType, self).write(vals)
# CUSTOM CODE BEFORE RECORD WRITE
return result
If you want to store field value in database then add store=True within your field in python file. Then Your value store into database.
From what i read you cannot return an action from an onchange function. But I want to show a dialog of some sort when a user changes the product within an orderline. The goal is to check if the product contains has_newproduct = True. In this case I want to ask the user if they want to delete the origin product (since it will not be needed).
I am overriding the onchange function of purchase order line like this:
class api_advanced(models.Model):
_inherit = "purchase.order.line"
has_newproduct = fields.Boolean("New Product")
#api.onchange('product_id')
def onchange_product_id(self):
_logger.debug("------------------- OLD PRODUCT ID ----------------")
_logger.debug(self._origin.product_id)
_logger.debug(self._origin.has_newproduct)
_logger.debug("------------------- NEW PRODUCT ID ----------------")
_logger.debug(self.product_id)
_logger.debug(self.has_newproduct)
# Code to fire wizard is here but it does nothing...
How would i have to acomplish something similar? Or do i have to do something totally different? I could just delete the product without asking but that's not really the goal here...
How you open wizard. when you click on button odoo calls a method,
method return a dictionary to the client side. the client side will
examine the returned value. client side know that this is an action to open a view.
What i'm trying to say this behavior is defined in javascript so if you
want some thing like that you should extends the form view to handle
the returned value from onchange event to open a wizard.
Or you can just add a button to the tree view with text delete orignal product
that button will appear only if has_newproduct = True (use related field to add it to tree so you can use it in attrs). The user will know that he can delete the orignal
product if he see that button and you can add confirm message to explain what
are the consequence of that operation.
I'm using Odoo 10. After a new user sign up (through localhost:8069/web/signup) i want him to be automatically allocated inside a group i created on my very own custom module (the user will need authentication from an admin later on so he can be converted to a regular portal user; after signup he will receive restricted access).
I have tried many things. My latest effort looks like this:
class RestrictAccessOnSignup(auth_signup_controller.AuthSignupHome):
def do_signup(self, *args):
super(RestrictAccessOnSignup, self).do_signup(*args)
request.env['res.groups'].sudo().write({'groups_id': 'group_unuser'})
Note that I have import odoo.addons.auth_signup.controllers.main as auth_signup_controller so that I can override the auth_signup controller.
I have located that method as the responsible for doing the signup. So I call it in my new method and then try to change the newly created user's group_id.
What i miss is a fundamental understanding of how to overwrite a field's value from another model inside a controller method context. I'm using the 'request' object although i'm not sure of it. I have seen people using 'self.pool['res.users'] (e.g.) for such purposes but i don't understand how to apply it inside my problem's context.
I believe, also, that there is a way to change the default group for a user after it is created (i would like to know), but i also want to understand how to solve the general problem (accessing and overwriting a field's value from another module).
Another weird thing is that the field groups_id does exist in 'res.users' model, but it does not appear as a column in my pgAdmin interface when i click to see the 'res.users' table... Any idea why?
Thanks a lot!
i don't know if after calling :
super(RestrictAccessOnSignup,self).do_signup(*args)
you will have access to user record in request object but if so just add
the group to user like this, if not you have to find where the user record or id is saved after calling do_signup because you need to update that record to ad this group.
# create env variable i hate typing even i'm typing here ^^
env = request.env
env.user.sudo().write({'groups_id': [
# in odoo relation field accept a list of commands
# command 4 means add the id in the second position must be an integer
# ref return an object so we return the id
( 4, env.ref('your_module_name.group_unuser').id),
]
})
and if changes are not committed in database you may need to commit them
request.env.cr.commit()
Note: self.env.ref you must pass the full xmlID.
This is what worked for me:
def do_signup(self, *args):
super(RestrictAccessOnSignup, self).do_signup(*args)
group_id = request.env['ir.model.data'].get_object('academy2', 'group_unuser')
group_id.sudo().write({'users': [(4, request.env.uid)]})
In the get_object i pass as arguments the 'module' and the 'xmlID' of the group i want to fetch.
It is still not clear to me why 'ir.model.data' is the environment used, but this works as a charm. Please note that here we are adding a user to the group, and not a group to the user, and to me that actually makes more sense.
Any further elucidation or parallel solutions are welcome, the methods aren't as clear to me as they should be.
thanks.
I'd like to ask, if is there any way to "disable" onchange decorator, when product is already created.
I have a field (X), which value depends, what will be in the 3 another fields (Y). I've used "api.onchange". When product is created, i want to make, that one of Y fields, will not change a value of X anymore.
I tryed to check, if "self" is existing in database, like exists(), but even new record is marked as "existing". I tryed to get access to self.id, but it's impossible. I thought about create additional field with Boolean type, but it's the last resort.
NEW API
First picture i added an onchange event to the name of product.template i used debug mode to stop the program and see if i have an acces to self._origin clearly i have access to it
Second picture it shows when I updated a product the ID value is passed
Now Third picture shows when i'm creating a new Product the value of the id in self._origin is False
so can you post the code that use used please i want to understand why you don't have acccess to self._origin
OLD API
when using old api self._origin is not access but you have the list of ids in edit mode the list will not be empty .
def onchange_name(self, cr, uid, ids, name, context=None):
# when updating a record ids will not be empty
# in my case will be ids=[55]
# in create mode the ids is empty
# id = []
if not ids :
# here you are in create mode you put your logic here
I want to add object level access control.
(Explaining it with dummy student-notice schema)
Student should access(edit/view) the notice(news) only if student has same class(standard) and subject assigned as that of notice.
There are two roles/groups - 'student' and 'teacher'
Database schema:
# model db.py
auth.define_tables(username=False, signature=True)
db.define_table('class', Field('name'))
db.define_table('subject', Field('name'))
db.define_table('notice', Field('title'),
Field('class', db.class),
Field('subject', db.subject))
db.define_table('user_class', Field('user', db.auth_user),
Field('class', db.class))
db.define_table('user_subject', Field('user', db.auth_user),
Field('subject', db.subject))
-
#controller default.py
def has_ownership():
# Check if logged in user has class and subject to view/edit this notice
pass
#auth.requires_login()
#auth.requires(lambda: has_ownership())
def notice():
user_classes = db(db.user_class.auth_user == auth.user.id).select()
user_class_list = [clss['id'] for clss in user_classes]
user_subjects = db(db.user_subject.auth_user == auth.user.id).select()
user_subject_list = [subject['id'] for subject in user_subjects]
query = db.notice.class.belongs(user_class_list) & db.notice.subject.belongs(user_subject_list)
grid = SQLFORM.grid(query, user_signature=True)
return dict(grid=grid)
All the urls are digitally signed and also i am showing records in the grid as per user's subject and class.
So my question is only digitally signed urls are enough to restrict user from accessing other records? (by changing id in the url)
Or i need to do extra check like i did using decorator has_ownership ?
Is there any other alternative to achieve object level access control in web2py? I dont want to use CRUD.
Thank You
Because the query already restricts the set of records displayed by the grid to those the user is authorized to access, the digitally signed URLs of the grid (which are enabled by default) are sufficient to prevent access to any other records. Not only will changes to the record ID in the URL be rejected, but if the user attempts to tamper with the hidden "id" form field in the edit form, the form submission will be rejected. So, no need for the has_ownership check.
As an aside, there is no need for a lambda when all the lambda does is call a single function with the same arguments passed to the lambda (in this case, no arguments). So, the decorator could be simplified to #auth.requires(has_ownership) (of course, you don't actually need the decorator in this case).