Marking projects as done when all tasks' progress are 100% We have project.task model, where each task has many lines and each line has progress field indicating how much work has been done and how much still remaining (from 0 to 100 percent). The task cannot be done until all lines' progress is 100%.

@api.onchange('task_line_ids','task_line_rider_ids')
def progress_on_change(self):
    for record in self:
        if len(record.task_line_ids) != 0 and record.state in ('open', 'done'):
            all_done = True
            for line in record.task_line_ids or record.task_line_rider_ids:
                if line.progress != 100:
                    all_done = False
                    break         
                if all_done == True:
                    record.state = 'done'
                else:
                    record.state = 'open'


However, SonarQube reported a code smell:


How can the complexity be reduced?
16 and 15 are pretty artificial values, you should aim for a better code quality rather than a higher/smaller metric in particular.

Let's see what can be improved...


Your boolean comparison if all_done == True: could (and should) be written in a more concise way: if all_done:.
Python has an optional else on for loops which can be understood as "this loop exited the usual way, not via a break". This removes the need for the all_done variable altogether:

if len(record.task_line_ids) != 0 and record.state in ('open', 'done'):
    for line in record.task_line_ids or record.task_line_rider_ids:
        if line.progress != 100:
            record.state = 'open'
            break         
    else:
        record.state = 'done'

You could use the all or any builtin to rewrite this without the for... else logic:

if len(record.task_line_ids) != 0 and record.state in ('open', 'done'):
    if all(line.progress == 100 for line in record.task_line_ids or record.task_line_rider_ids):
        record.state = 'done'
    else:
        record.state = 'open'

You could re-introduce the temporary variable and use ternary operator:

if len(record.task_line_ids) != 0 and record.state in ('open', 'done'):
    all_done =  all(line.progress == 100 for line in record.task_line_ids or record.task_line_rider_ids)
    record.state = 'done' if all_done else 'open'