Connectors mailing list archives

connectors@odoo-community.org

Avatar

[Solved] Fwd: Help with the framework 'connector'

by
cyrille
- 05/04/2019 10:12:34



-------- Forwarded Message --------
Subject: Re: Help with the framework 'connector'
Date: Thu, 4 Apr 2019 11:02:09 +0200
From: cyrille <cyrille@lalibrerie.org>
To: Günter Selbert | sewisoft UG <guenter.selbert@sewisoft.de>


Thanks for your answer.

I modified the line : binder.bind(external_id=project_data.id, binding=new_binding.id) by removing '.id' to the binding attribute. I didn’t realized I had to pass the record and not just the id.

Also, I had to modify this line : with backend.work_on(model_name='trello.project.backend') as work, to put the binding model as model_name. That was why the binder was looking the 'external_id' in the backend model instead of the binding and gave me the WARNING I had. And I guess the 'to_internal' function was then also trying to work with the backend model, instead of the binding.

The test pass now.

Thanks.

Cyrille (La LibreRie)


On 03/04/2019 12:58, Günter Selbert | sewisoft UG wrote:

Hi,

you try to bind the external_id to the backend which is wrong, you need to bind back the id to the binding record. Check the call of the binders method "bind" or it's implementation, you must write here on the binding! The method should look like this:


def bind(self, external_id, binding):
    """ Create the link between an external ID and an Odoo ID

    :param external_id: external id to bind
    :param binding: Odoo record to bind
    :type binding: int
    """
    # Prevent False, None, or "", but not 0
    assert (external_id or external_id is 0) and binding, (
            "external_id or binding missing, "
            "got: %s, %s" % (external_id, binding)
    )
    # avoid to trigger the export when we modify the `external_id`
    now_fmt = fields.Datetime.now()
    if isinstance(binding, models.BaseModel):
        binding.ensure_one()
    else:
        binding = self.model.browse(binding)
    binding = binding.with_context(connector_no_export=True)
    binding.write({self._external_field: tools.ustr(external_id), self._sync_date_field: now_fmt})

and it needs to be called like this at the end of the importers run method:

self.binder.bind(self.external_id, binding_record)


Vielen Dank und viele Grüße

Günter Selbert
Geschäftsführer
sewisoft.de - Logo

sewisoft UG
Örtleinsweg 39
96148 Baunach

info@sewisoft.de
www.sewisoft.de

Sitz der Gesellschaft: Baunach
Registergericht: Amtsgericht Bamberg, HRB 8508
Geschäftsführer: Günter Selbert, Stefan Wild



Am 03.04.19 um 12:47 schrieb cyrille:

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