Don Kirkby
Don Kirkby

Reputation: 56590

Overriding OpenERP constraints

I want to write a module that overrides one of the constraints on a model object, but just overriding the constraint method doesn't work. My override of the method never gets called, because OpenERP uses its own inheritance mechanism.

I'm trying to make the rules about sign in / sign out actions a little more flexible in the hr_timesheet_sheet module so that employees can record hours on a previous day after they've signed in today. To do that, I want to override the hr.attendance constraint on the action field and allow any changes, then perform a check at the timesheet level that all the attendance actions are in a logical sequence.

I found the hr.attendance constraint.

def _altern_si_so(self, cr, uid, ids, context=None):
    """ Alternance sign_in/sign_out check.
        Previous (if exists) must be of opposite action.
        Next (if exists) must be of opposite action.
    """
    for att in self.browse(cr, uid, ids, context=context):
        # search and browse for first previous and first next records
        prev_att_ids = self.search(cr, uid, [('employee_id', '=', att.employee_id.id), ('name', '<', att.name), ('action', 'in', ('sign_in', 'sign_out'))], limit=1, order='name DESC')
        next_add_ids = self.search(cr, uid, [('employee_id', '=', att.employee_id.id), ('name', '>', att.name), ('action', 'in', ('sign_in', 'sign_out'))], limit=1, order='name ASC')
        prev_atts = self.browse(cr, uid, prev_att_ids, context=context)
        next_atts = self.browse(cr, uid, next_add_ids, context=context)
        # check for alternance, return False if at least one condition is not satisfied
        if prev_atts and prev_atts[0].action == att.action: # previous exists and is same action
            return False
        if next_atts and next_atts[0].action == att.action: # next exists and is same action
            return False
        if (not prev_atts) and (not next_atts) and att.action != 'sign_in': # first attendance must be sign_in
            return False
    return True

_constraints = [(_altern_si_so, 'Error: Sign in (resp. Sign out) must follow Sign out (resp. Sign in)', ['action'])]

I tried overriding the constraint method in my module, but my version never got called.

def _altern_si_so(self, cr, uid, ids):
    """ Implementing this logic at the attendance level doesn't work, so
    we skip it, and check at the whole time sheet level. 's all good!"""
    return True

I also tried adding my own constraint on the same field, but then it called both versions and the base module's constraint could reject the save.

Upvotes: 1

Views: 1486

Answers (1)

Don Kirkby
Don Kirkby

Reputation: 56590

I found a bug on launchpad that describes the problem I'm having and the fix. It turns out that you can override constraints now, but it's very fiddly. You have to declare your own constraint on the same field with the same function name as the base module. Then and only then will it call your constraint instead of the base version.

Here's my module that overrides the hr_attendance constraint on actions and allows any combination.

class hr_attendance(osv.osv):
    _inherit = 'hr.attendance'

    def _altern_si_so(self, cr, uid, ids):
        """ Implementing this logic at the attendance level doesn't work, so
        we skip it, and check at the whole time sheet level. 's all good!"""
        return True

    _constraints = [(_altern_si_so, 
                     'Error: You should never see this message.', 
                     ['action'])]

Upvotes: 3

Related Questions