Connectors mailing list archives

connectors@odoo-community.org

Avatar

Re: Help with the framework 'connector'

by
Quentin THEURET
- 04/04/2019 14:03:48

Hi Cyrille,

Have you tried by removing the AbstractModel and put the `external_id` field definition on the `trello.project.binding` object ?

Regards,

--

Quentin

Le 03/04/2019 à 12:47, cyrille a écrit :

Hi,

I’m trying to build a Trello connector, using the connector v 11.0 module. I’m having some trouble with using the binding object. I built a backend, a binding, linked to the backend and extended the 'project.project' model with classic inheritance. The binding is also linked to the 'project.project' model with many-to-one relationship.


class TrelloProjectBackend(models.Model):
    _name='trello.project.backend'
    _description='Trello Project Backend'
    _inherit='trello.abstract.backend'

    @api.model
    def read_projects(self, client):
        #getting unique backend reference
        backend = self.get_unique_backend(backend_type='project')

        with backend.work_on(model_name='trello.project.backend') as work:
            adapter = work.component(usage='backend.adapter')
            binder = work.component(usage='project.binder')
            bindings = self.env['trello.project.binding']
            projects = self.env['project.project']
            work.projects_data = adapter.read(client=client)
            stages_data = []

            for project_data in work.projects_data:
                new_project = projects.create({
                    'name': project_data.name,
                    'board_url': project_data.url,
                    'desc': project_data.description,
                    'is_linked_to_trello': True,
                })

                new_binding = bindings.create({
                    'odoo_id': new_project.id,
                    'backend_id': backend.id,
                    'external_id': project_data.id,
                    'sync_date': datetime.datetime.now(),
                })
                binder.bind(external_id=project_data.id, binding=new_binding.id)
                stages_data.append({'project_id': new_project.id, 'stages_data': project_data.all_lists()})

            self.env['trello.stage.backend'].push_stages(data=stages_data)

            logging.debug("getting binder data")
            b_1 = binder.to_internal(project_data.id, unwrap=False)
            b_2 = binder.to_internal(project_data.id, unwrap=True)

            logging.debug("bindings for unwrap False: {}".format(b_1.__repr__()))
            logging.debug("bindings for unwrap True: {}".format(b_2.__repr__()))


class TrelloAbstractBinding(models.AbstractModel):
    _name='trello.abstract.binding'
    _inherit='external.binding'

    external_id=fields.Integer('ID in Trello')



class TrelloProjectBinding(models.Model):
    _name='trello.project.binding'
    _inherit='trello.abstract.binding'
    _inherits={'project.project': 'odoo_id'}

    odoo_id=fields.Many2one(
        comodel_name='project.project',
        string='Project',
        required=True,
        ondelete='cascade',
    )

    backend_id=fields.Many2one(
        comodel_name='trello.project.backend',
        string='Project Binding',
        required=True,
        ondelete='restrict',
    )

    _sql_constraints = [
        ('project_uniq', 'unique(backend_id, odoo_id)', 'Project with same ID already exists.')
    ]


class TrelloProject(models.Model):
    _inherit='project.project'

    desc=fields.Text('Description')
    board_url=fields.Text('Trello Board URL', readonly=True)
    is_linked_to_trello=fields.Boolean(default=False, readonly=True)

    @api.model
    def import_projects(self):
        client = self.env.user.get_trello_client()
        self.env['trello.project.backend'].read_projects(client=client)



I built a test scenario, to check if the building of new record from imported data is correctly executed :

class TestTrelloProjectBackend(TransactionCase):

    def setUp(self, *args, **kwargs):
        super(TestTrelloProjectBackend, self).setUp(*args, **kwargs)

    @mock.patch('trello.TrelloClient')
    @mock.patch('trello.Board')
    @mock.patch('trello.List')
    @mock.patch('trello.Card')
    def test_read_projects(self, mock_trello_card, mock_trello_list, mock_trello_board, mock_trello_client):

        trello_backend = self.env['trello.project.backend'].create({})

        mock_trello_card.id = '789'
        mock_trello_card.name = 'Mock Card Name'
        mock_trello_card.due = '2019-01-30T12:40:37.123Z'

        mock_trello_list.id = '456'
        mock_trello_list.name = 'Mock List Name'
        mock_trello_list.closed = False
        mock_trello_list.pos = 2
        mock_trello_list.list_cards.return_value = [mock_trello_card]
        mock_trello_card.parent = mock_trello_list

        mock_trello_board.id = '123'
        mock_trello_board.name = 'Mock Board Name'
        mock_trello_board.description = 'A mocked object to replace board object from py-trello library'
        mock_trello_board.closed = False
        mock_trello_board.url = 'http://fake.url.org/mockboardid'
        mock_trello_board.all_lists.return_value = [mock_trello_list]

        mock_trello_list.board = mock_trello_board

        mock_trello_client.list_boards.return_value = [mock_trello_board]

        trello_backend.read_projects(mock_trello_client)

        mock_trello_client.list_boards.assert_called_once_with()

        new_project = self.env['project.project'].search([('name','=','Mock Board Name')])

        new_project.ensure_one()
        self.assertEqual(new_project.name, 'Mock Board Name')
        self.assertEqual(new_project.board_url, 'http://fake.url.org/mockboardid')
        self.assertEqual(new_project.desc, 'A mocked object to replace board object from py-trello library')



The test fails with the following error :

ERROR
======================================================================
ERROR: test_read_projects (odoo.addons.connector_trello.tests.test_trello_project_backend.TestTrelloProjectBackend)
Traceback (most recent call last):
`   File "/usr/lib/python3/dist-packages/mock/mock.py", line 1305, in patched
`     return func(*args, **keywargs)
`   File "/home/cyrille/odoo/addons-dev/connector_trello/tests/test_trello_project_backend.py", line 42, in test_read_projects
`     trello_backend.read_projects(mock_trello_client)
`   File "/home/cyrille/odoo/addons-dev/connector_trello/models/backends/trello_project_backend.py", line 57, in read_projects
`     b_1 = binder.to_internal(project_data.id, unwrap=False)
`   File "/home/cyrille/odoo/addons-ext/connector/components/binder.py", line 53, in to_internal
`     (self._backend_field, '=', self.backend_record.id)]
`   File "/opt/odoo/odoo/odoo/models.py", line 1480, in search
`     res = self._search(args, offset=offset, limit=limit, order=order, count=count)
`   File "/opt/odoo/odoo/odoo/models.py", line 3773, in _search
`     query = self._where_calc(args)
`   File "/opt/odoo/odoo/odoo/models.py", line 3563, in _where_calc
`     e = expression.expression(domain, self)
`   File "/opt/odoo/odoo/odoo/osv/expression.py", line 668, in __init__
`     self.parse()
`   File "/opt/odoo/odoo/odoo/osv/expression.py", line 846, in parse
`     raise ValueError("Invalid field %r in leaf %r" % (left, str(leaf)))
` ValueError: Invalid field 'external_id' in leaf "<osv.ExtendedLeaf: ('external_id', '=', '123') on trello_project_backend (ctx: )>"


I can’t figure out what is wrong with the 'external_id' field.


I don’t know if it is linked to my problem, but I have this warning I can’t understand : 

WARNING db_odoo_test_1 odoo.models: trello.task.backend.write() with unknown fields: external_id, sync_date

There is no external_id and sync_date fields in the backends, but maybe it should.


Thanks for reading,

Sincerely,

Cyrille (La LibreRie)

lalibrerie-solidaire.org

Python/Odoo developper

_______________________________________________
Mailing-List: https://odoo-community.org/groups/connectors-30
Post to: mailto:connectors@odoo-community.org
Unsubscribe: https://odoo-community.org/groups?unsubscribe

-- 
Quentin THEURET
Amaris

Reference