Skip to content

Commit

Permalink
[FIX] connector_carepoint: Fix create and write functionality
Browse files Browse the repository at this point in the history
* Add primary key injection in create
* Prefer Pk return in create to Recordset - comma join in col order
* Remove carepoint update method in favor of custom write logic
* Fix export synchronizer carepoint_id assignment
  • Loading branch information
lasley committed Sep 13, 2016
1 parent c8c40ce commit 09c979a
Show file tree
Hide file tree
Showing 7 changed files with 314 additions and 51 deletions.
38 changes: 24 additions & 14 deletions connector_carepoint/consumer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

# from openerp.addons.connector.connector import Binder
from .unit.export_synchronizer import (export_record,
)
from .unit.export_synchronizer import export_record
# from .unit.delete_synchronizer import export_delete_record
# from .connector import get_environment
# from openerp.addons.connector.event import (on_record_write,
# on_record_create,
# on_record_unlink
# )
from openerp.addons.connector.event import (on_record_write,
on_record_create,
# on_record_unlink
)


import logging
Expand All @@ -21,10 +20,6 @@
# 'carepoint.carepoint.address',
# 'carepoint.carepoint.address.patient',
# ])
# @on_record_write(model_names=['carepoint.medical.patient',
# 'carepoint.carepoint.address',
# 'carepoint.carepoint.address.patient',
# ])
def delay_export(session, model_name, record_id, vals):
""" Delay a job which export a binding record.
(A binding record being a ``carepoint.res.partner``,
Expand All @@ -36,10 +31,8 @@ def delay_export(session, model_name, record_id, vals):
export_record.delay(session, model_name, record_id, fields=fields)


# @on_record_write(model_names=['medical.patient',
# 'carepoint.address',
# 'carepoint.address.patient',
# ])
@on_record_write(model_names=['carepoint.address',
])
def delay_export_all_bindings(session, model_name, record_id, vals):
""" Delay a job which export all the bindings of a record.
In this case, it is called on records of normal models and will delay
Expand All @@ -54,6 +47,23 @@ def delay_export_all_bindings(session, model_name, record_id, vals):
fields=fields)


@on_record_create(model_names=['carepoint.address',
])
def delay_create(session, model_name, record_id, vals):
""" Create a new binding record, then trigger delayed export
In this case, it is called on records of normal models to create
binding record, and trigger external system export
"""
model_obj = session.env['carepoint.%s' % model_name].with_context(
connector_no_export=True,
)
if not len(model_obj.search([('odoo_id', '=', record_id)])):
model_obj.create({
'odoo_id': record_id,
})
delay_export_all_bindings(session, model_name, record_id, vals)


# @on_record_unlink(model_names=['carepoint.medical.patient',
# 'carepoint.carepoint.address',
# 'carepoint.carepoint.address.patient',
Expand Down
114 changes: 113 additions & 1 deletion connector_carepoint/models/address_abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

import logging
from openerp import models, fields, api
from openerp import models, fields, api, _
from openerp.addons.connector.unit.mapper import (mapping,
only_create,
ExportMapper,
)
from ..unit.mapper import CarepointImportMapper
from ..backend import carepoint
from ..unit.import_synchronizer import CarepointImporter
from ..unit.export_synchronizer import CarepointExporter

from .address import CarepointAddress

Expand Down Expand Up @@ -37,11 +39,35 @@ class CarepointAddressAbstract(models.AbstractModel):
string='Partner',
comodel_name='res.partner',
required=True,
store=True,
compute='_compute_partner_id',
inverse='_set_partner_id',
)
res_model = fields.Char(
string='Resource Model',
default=lambda s: s._default_res_model(),
)
res_id = fields.Integer(
string='Resource PK',
compute='_compute_res_id',
store=True,
)

@property
@api.multi
def medical_entity_id(self):
self.ensure_one()
return self.env[self.res_model].browse(self.res_id)

@api.model
def _default_res_model(self):
""" It returns the res model. Should be overloaded in children """
raise NotImplementedError(
_('_default_res_model should be implemented in child classes')
)

@api.multi
@api.depends('partner_id')
def _compute_partner_id(self):
""" It sets the partner_id from the address_id """
for rec_id in self:
Expand Down Expand Up @@ -71,6 +97,44 @@ def _set_partner_id(self):
else:
rec_id.address_id.write(vals)

@api.multi
@api.depends('partner_id', 'res_model')
def _compute_res_id(self):
""" It computes the resource ID from model """
for rec_id in self:
if not all([rec_id.res_model, rec_id.partner_id]):
continue
medical_entity = self.env[rec_id.res_model].search([
('partner_id', '=', rec_id.partner_id.id),
],
limit=1,
)
rec_id.res_id = medical_entity.id

@api.model
def _get_by_partner(self, partner, create=True, recurse=False):
""" It returns the address associated to the partner.
Params:
partner: Recordset singleton of partner to search for
create: Bool determining whether to create address if not exist
recurse: Bool determining whether to recurse into children (this
is only really useful when create=True)
Return:
Recordset of partner address
"""
address = self.search([('partner_id', '=', partner.id)], limit=1)
vals = self.address_id._get_partner_sync_vals(partner)
_logger.info('_get_by_partner %s, %s, %s' % (address, partner, vals))
if not address and create:
vals['partner_id'] = partner.id
address = self.create(vals)
else:
address.write(vals)
if recurse:
for child in partner.child_ids:
self._get_by_partner(child, create, recurse)
return address


@carepoint
class CarepointAddressAbstractImportMapper(CarepointImportMapper):
Expand Down Expand Up @@ -116,6 +180,19 @@ def partner_id(self, record, medical_entity):
partner = self.env['res.partner'].create(vals)
return {'partner_id': partner.id}

def res_model_and_id(self, record, medical_entity):
""" It returns the vals dict for res_model and res_id
Params:
record: ``dict`` of carepoint record
medical_entity: Recordset with a ``partner_id`` column
Return:
``dict`` of values for mapping
"""
return {
'res_id': medical_entity.id,
'res_model': medical_entity._name,
}

@mapping
@only_create
def address_id(self, record):
Expand All @@ -139,3 +216,38 @@ def _create(self, data):
self.session, binding._name, binding.id, binding.backend_id.id
)
return binding


@carepoint
class CarepointAddressAbstractExportMapper(ExportMapper):

@mapping
def addr_id(self, binding):
binder = self.binder_for('carepoint.carepoint.address')
rec_id = binder.to_backend(binding.address_id.id)
return {'addr_id': rec_id}

@mapping
def static_defaults(self, binding):
return {
'priority': 2,
'addr_type_cn': 2,
'app_flags': 0,
}


@carepoint
class CarepointAddressAbstractExporter(CarepointExporter):

@mapping
def _export_dependencies(self):
model = self._model_name
if isinstance(model, list):
model = model[0]
_logger.debug(
_('_model_name was a list, using %s from %s') % (
self._model_name, model,
)
)
self._export_dependency(self.binding_record.address_id,
model)
108 changes: 105 additions & 3 deletions connector_carepoint/tests/models/test_address_abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,12 @@ def new_address(self, partner=None):
return self.env['carepoint.address'].create(vals)

def new_patient_address(self):
patient = self.new_patient()
self.address = self.new_address(patient.partner_id)
self.patient = self.new_patient()
self.address = self.new_address(self.patient.partner_id)
return self.model.create({
'partner_id': patient.partner_id,
'partner_id': self.patient.partner_id.id,
'address_id': self.address.id,
'res_model': 'medical.patient',
})

def test_compute_partner_id(self):
Expand Down Expand Up @@ -94,6 +95,21 @@ def test_set_partner_id_with_address(self):
address.street,
)

def test_medical_entity_id(self):
""" It should return patient record """
address = self.new_patient_address()
self.assertEqual(
self.patient,
address.medical_entity_id,
)

def test_compute_res_id(self):
address = self.new_patient_address()
self.assertEqual(
self.patient.id,
address.res_id,
)


class TestAddressAbstractImportMapper(AddressAbstractTestBase):

Expand Down Expand Up @@ -172,6 +188,16 @@ def test_address_id_return(self):
expect = self.unit.binder_for().to_odoo()
self.assertDictEqual({'address_id': expect}, res)

def test_res_model_and_id(self):
""" It should return values dict for medical entity """
entity = mock.MagicMock()
expect = {
'res_id': entity.id,
'res_model': entity._name,
}
res = self.unit.res_model_and_id(None, entity)
self.assertDictEqual(expect, res)


class TestAddressAbstractImporter(AddressAbstractTestBase):

Expand All @@ -191,3 +217,79 @@ def test_import_dependencies(self):
'carepoint.carepoint.address',
),
])


class TestAddressAbstractExportMapper(AddressAbstractTestBase):

def setUp(self):
super(TestAddressAbstractExportMapper, self).setUp()
self.Unit = address_abstract.CarepointAddressAbstractExportMapper
self.unit = self.Unit(self.mock_env)
self.record = mock.MagicMock()

def test_addr_id_get_binder(self):
""" It should get binder for prescription line """
with mock.patch.object(self.unit, 'binder_for'):
self.unit.binder_for.side_effect = EndTestException
with self.assertRaises(EndTestException):
self.unit.addr_id(self.record)
self.unit.binder_for.assert_called_once_with(
'carepoint.carepoint.address'
)

def test_addr_id_to_backend(self):
""" It should get backend record for rx """
with mock.patch.object(self.unit, 'binder_for'):
self.unit.binder_for().to_backend.side_effect = EndTestException
with self.assertRaises(EndTestException):
self.unit.addr_id(self.record)
self.unit.binder_for().to_backend.assert_called_once_with(
self.record.address_id.id,
)

def test_addr_id_return(self):
""" It should return formatted addr_id """
with mock.patch.object(self.unit, 'binder_for'):
res = self.unit.addr_id(self.record)
expect = self.unit.binder_for().to_backend()
self.assertDictEqual({'addr_id': expect}, res)

def test_static_defaults(self):
""" It should return a dict of default values """
self.assertIsInstance(
self.unit.static_defaults(self.record),
dict,
)


class TestAddressAbstractExporter(AddressAbstractTestBase):

def setUp(self):
super(TestAddressAbstractExporter, self).setUp()
self.Unit = address_abstract.CarepointAddressAbstractExporter
self.unit = self.Unit(self.mock_env)
self.record = mock.MagicMock()
self.unit.binding_record = self.record

def test_export_dependencies_export(self):
""" It should export all dependencies """
with mock.patch.object(self.unit, '_export_dependency') as mk:
self.unit._export_dependencies()
mk.assert_has_calls([
mock.call(
self.record.address_id,
self.unit._model_name,
),
])

def test_export_dependencies_list(self):
""" It should correctly handle list _model_name as list """
with mock.patch.object(self.unit, '_export_dependency') as mk:
self.unit._model_name = ['expect']
self.unit._export_dependencies()
mk.assert_has_calls([
mock.call(
self.record.address_id,
self.unit._model_name[0],
),
])
Loading

0 comments on commit 09c979a

Please sign in to comment.