I need to change the state of a field to 'readonly' programmatically

I have this model

class UserTimesheet(ModelSQL, ModelView):
    "User Timesheet"
    __name__ = 'afx.user.timesheet'

    # Hardcoded
    MAIN_COMPANY = 1
    UUID_PREFIX = "tsr_"
    ADMIN = "Timesheet Administration"

    _is_admin = fields.Boolean('_is_admin')

    year = fields.Selection([], "Year", help='Format: YYYY', required=True, states={
        'readonly': Eval('id', -1) > 0
    }, depends=['id'])
    month = fields.Selection([], "Month", sort=False, required=True, states={
        'readonly': Eval('id', -1) > 0
    }, depends=['id'])
    user = fields.Many2One('company.employee', "User", required=True, domain=[
        ('company', '=', MAIN_COMPANY)], states={
            'readonly': Eval('_is_admin', False) != True
        })
    unique_id = fields.Char("Uuid", required=True)

    records = fields.One2Many('afx.user.timesheet.record', 'timesheet', "Records", required=False)

And I want to change the states of ‘user’ to ‘readonly’ programmatically when the user is not an admin. Because they cannot change the value to someone else.

I tried to change during default_user(cls) (see below) execution but now both admin and non-admin got their user field in UI read-only

    # ------- DEFAULT VALUES --------    
    @classmethod
    def default_user(cls):
        # Get the logged-in user's ID
        user_id = Transaction().user

        # Get required models from pool to get user's group to determine search
        # limitation
        pool = Pool()
        UserGroup = pool.get('res.user-res.group')
        Group = pool.get('res.group')

        current_user_groups = UserGroup.search([
            ('user', '=', user_id)
        ])

        _is_admin = False
        if current_user_groups:
            for user_group in current_user_groups:
                group = Group.search([
                    ('id', '=', user_group.group)
                ])
                if group:
                    if group[0].name == cls.ADMIN:
                        _is_admin = True
        
        if _is_admin == False:
            cls._is_admin = False <----- HERE
            return Transaction().user
        else:
            cls._is_admin = True <----- HERE
            return None

I know I can Group other than admin to only have read access, but on other business process a normal user can perform update to this model.. so its kind of tricky.
I am thinking of change the state programmatically ..
Can anybody advice me?

Regards
Bromo

Probably the easiest way is to just store the user and use a function field to compute if the user is admin or not.

Hope this helps!

1 Like

You can not use property nor attribute in a PYSON statement.
You can only use Tryton fields, so in this cas a Function field using an on_change_with* as getter seems the best option.

1 Like