'Serializes one2many and many2many commands into record dictionaries
(as if all the records came from the database via a read()).  This
method is aimed at onchange methods on one2many and many2many fields.
Because commands might be creation commands, not all record dicts
will contain an ``id`` field.  Commands matching an existing record
will have an ``id``.
:param field_name: name of the one2many or many2many field matching the commands
:type field_name: str
:param commands: one2many or many2many commands to execute on ``field_name``
:type commands: list((int|False, int|False, dict|False))
:param fields: list of fields to read from the database, when applicable
:type fields: list(str)
:returns: records in a shape similar to that returned by ``read()``
(except records may be missing the ``id`` field if they don\'t exist in db)
:rtype: list(dict)'

@api.model
def resolve_2many_commands(self, field_name, commands, fields=None):

    result = []
    record_ids = []
    updates = defaultdict(dict)
    for command in (commands or []):
        if (not isinstance(command, (list, tuple))):
            record_ids.append(command)
        elif (command[0] == 0):
            result.append(command[2])
        elif (command[0] == 1):
            record_ids.append(command[1])
            updates[command[1]].update(command[2])
        elif (command[0] in (2, 3)):
            record_ids = [id for id in record_ids if (id != command[1])]
        elif (command[0] == 4):
            record_ids.append(command[1])
        elif (command[0] == 5):
            (result, record_ids) = ([], [])
        elif (command[0] == 6):
            (result, record_ids) = ([], list(command[2]))
    field = self._fields[field_name]
    records = self.env[field.comodel_name].browse(record_ids)
    for data in records.read(fields):
        data.update(updates.get(data['id'], {}))
        result.append(data)
    return result
