Shall I record the user name who modify a certain field by Odoo? - odoo

.py file:
….
namex=fields.Text()
moifier=fields.Many2one(‘res.users’, string=”Modifier”)
…
When some user modify “namex”, his/her name should be recorded on field “modifier” automatically; what code should I make? I try “onchange/depends”, but failed; maybe modifier could be a “text field/ char field”?
in addition, shall I set "access_rule" to set users just see the records created by the members in his/her own group?

Odoo already has that for you. Every model has those fields, which are automatically created and updated each time you create, or write:
create_date (datetime): when record is created
create_uid (many2one): user who created this record
write_date (datetime): last time record is updated
write_uid (many2one): last user updated this record
Go to Settings > Technical > Database Structure > Models for more details.

While Odoo will keep for you a track of the last user which has modified a record, a modifier per field is not kept. I can see the interest of such a functionality in many cases.
To do that for a particular model one possibility is to redefine the write method of this model. In your .py file you may want to add something like this:
#api.model
def write(self):
if self.namex in values:
values.update({'modifier': uid})
super().write(cr, uid, ids, values, context)
Another way to do that in a more flexible way is to use the #onchange decorator:
#onchange('your_sensible_field_name'):
def set_modifier(self):
self.modifer = self.env.user
You may also want to take a look at the #depends decorator.

Related

Restrict write permissions for a field - Odoo 15

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')]}"}"/>

How to store logged user in Odoo14

I am trying to store the currently logged user into a many2one field using compute method. It's working fine if i define the Mnay2one field without the store="True" parameter. Actually, i need to save it.
Here is the code:
def get_logged_user(self):
for rec in self:
print('inside get_logged_user---------------',rec.env.user.name)
rec.logged_user_id = rec.env.user.id
logged_user_id = fields.Many2one('res.users',string="Logged user",store=True,compute="get_logged_user")
EDIT:
If you only need to control visibility of a field/button inside QWeb view you could archive this without dedicated field. You could use context.get('uid') to get current user like this:
<button ... invisible="context.get('uid') == assigned_user_id">
But if you need to store logged-in user inside a field you could use default instead of compute.
Something like this:
logged_user_id = fields.Many2one('res.users', string="Logged user", default=lambda self: self.env.user)
Note usage of lambda function.
If you really need to use compute field with store=True you need to specify when to compute it. By using api.depends decorator you can trigger it when your_field is changed.
#api.depends('your_field')
def get_logged_user(self):
But I would ask a question why do you need to store logged-in user inside a field? If you could provide more context maybe we could suggest different solution.

How to relate fields in Odoo 11 CE

I added a custom field in "account.payment" model, I also added it in "account.move.line" model (aka: Journal Item).
The value of the custom field is entered from account.payment and since the journal items are generated from a payment creation I want to do the following:
If account.move.line.id is created by account.payment.id
let account.move.line.custom_field = account.payment.custom_field
I appreciate your help
You have to find in account.move.line that represent the relation(foreign_key) with account.payment, let says payment_id, this field allows you to access to account.payment model, and for your case you just need to do:
field_in_account_move_line = payment_id.field_in_account_payment
I hope this answer can be helpful for you.

working of openerp-create & write orm methods

can anyone explain the working of create and write orm mehods in openerp ? Actually I'm stuck at this methods,I'm not getting how it works internally and how can I implement it over a simple program.
class dumval(osv.osv):
_name = 'dum_val'
_columns={
'state':fields.selection([('done','confirm'),('cancel','cancelled')],'position',readonly=True),
'name':fields.char('Name',size=40,required=True,states={'done':[('required','False')]}),
'lname':fields.char('Last name',size=40,required=True),
'fname':fields.char('Full name',size=80,readonly=True),
'addr':fields.char('Address',size=40,required=True,help='enter address'),
}
_defaults = {
'state':'done',
}
It would be nice if u could explain using this example..
A couple of comments plus a bit more detail.
As Lukasz answered, convention is to use periods in your model names dum.val. Usually something like my_module.my_model to ensure there are no name collisions (e.g. account.invoice, sale.order)
I am not sure if your conditional "required" in the model will work; this kind of thing is usually done in the view but it would be worth seeing how the field is defined in the SQL schema.
The create method creates new records (SQL Insert). It takes a dict of values, applies any defaults you have specified and then inserts the record and returns the new ID. Note that you can do compound creates, i.e. if you are creating and invoice, you can add the invoice lines into the dictionary and do it all in one create and OpenERP will take care of the related fields for you (ref write method in https://doc.openerp.com/trunk/server/api_models/)
The write method updates existing records (SQL Update). It takes a dict of values and applies to all of the ids you pass. This is an important point, if you pass a list of ids, the values will be written to all ids. If you want to update a single record, pass a list of one entry, if you want to do different updates to the records, you have to do multiple write calls. You can also manage related fields with a write.
It's convention to give _name like dum.val instead of dum_val.
In dumval class you can write a method:
def abc(cr, uid, ids, context=None):
create_dict = {'name':'xxx','lname':'xxx','fname':'xxx','addr':'xyz'}
# create new object and get id
new_id = self.create(cr, uid, write_dict, context=context)
# write on new object
self.write(cr, uid, new_id, {'lname':'yyy'}, context=context)
For more details look: https://www.openerp.com/files/memento/older_versions/OpenERP_Technical_Memento_v0.6.1.pdf

Ruby/Rails - Implicitly create a parent record when creating a child record?

Ok this is a bit unusual, but I have a series of data collection forms that save data to their respective models. What I want to do is auto insert a common parent (activity/event log - separate model) record that will be common to each form. (All forms will save an implicit record in this model, before saving the child record). So the save sequence needs to be as follows:
1) On each detail form capture user input
2) Create a new parent record containing summary info (User ID, Record Type, Timestamp)
3) Capture the new Parent PK value for insertion (as a Foreign Key) into the detail record
4) Populate the detail record with user input data and the FK data, then save
5) Commit (or Rollback)
How can I do this - where are the hooks for something like this? Obviously I need to override some default bahaviour in Rails to do this - has anyone seen any examples that they can share?
TIA,
Brendan
P.S. Before you think this is a bass ackwards approach , I need to handle the use case where an activity/significant event occurs, but the underlying detail info is unavailable.
(This is likely to arise with externally imported data when only the parent will get created). Right now I'm primarily interested in exploring a Rails solution to this.
There are several ways to achieve this, depending on How you want it.
before_save filter in your child record model,
class YourModel < ActiveRecord::Base
before_save :create_parent
def create_parent
#do something here
end
end
Active Record Observers ( follows a observer pattern )
This goes in your environment.rb file
config.active_record.observers = :yourmodel_observer
create a yourmodel_observer.rb file
and code
class YourModelObserver < ActiveRecord::Observer
def after_save(object)
end
def after_update(object)
end
end