diff --git a/connector_carepoint/connector.py b/connector_carepoint/connector.py index 0215080..1b92412 100644 --- a/connector_carepoint/connector.py +++ b/connector_carepoint/connector.py @@ -2,7 +2,7 @@ # Copyright 2015-2016 LasLabs Inc. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import models, fields +from openerp import models, fields, api from openerp.addons.connector.connector import ConnectorEnvironment from openerp.addons.connector.checkpoint import checkpoint @@ -53,7 +53,7 @@ class CarepointBinding(models.AbstractModel): @api.model def _default_backend_id(self): - return self.env['easypost.backend'].search([ + return self.env['carepoint.backend'].search([ ('is_default', '=', True), ('active', '=', True), ], diff --git a/connector_carepoint/data/carepoint_carepoint_account_data.xml b/connector_carepoint/data/carepoint_carepoint_account_data.xml index 0efa285..fb59bd2 100644 --- a/connector_carepoint/data/carepoint_carepoint_account_data.xml +++ b/connector_carepoint/data/carepoint_carepoint_account_data.xml @@ -1,16 +1,9 @@ - - + - - Null Patient - - - - - - 0 - + + Null Patient + + - - + diff --git a/connector_carepoint/models/__init__.py b/connector_carepoint/models/__init__.py index 847e1ed..cb76fdd 100644 --- a/connector_carepoint/models/__init__.py +++ b/connector_carepoint/models/__init__.py @@ -12,12 +12,12 @@ from . import procurement_order from . import account_invoice_line from . import stock_picking +from . import stock_warehouse # Medical Models from . import medical_pharmacy from . import medical_patient from . import medical_physician -from . import medical_medicament from . import medical_prescription_order from . import medical_prescription_order_line @@ -30,6 +30,8 @@ # CarePoint Mappings/Binds from . import account from . import carepoint_state +from . import carepoint_item +from . import carepoint_vendor # FDB from . import fdb_ndc diff --git a/connector_carepoint/models/carepoint_backend.py b/connector_carepoint/models/carepoint_backend.py index 4400e4d..7c47676 100644 --- a/connector_carepoint/models/carepoint_backend.py +++ b/connector_carepoint/models/carepoint_backend.py @@ -155,7 +155,7 @@ class CarepointBackend(models.Model): comodel_name='account.payment.term', required=True, ) - import_medicaments_from_date = fields.Datetime() + import_items_from_date = fields.Datetime() import_patients_from_date = fields.Datetime() import_physicians_from_date = fields.Datetime() import_prescriptions_from_date = fields.Datetime() @@ -291,9 +291,9 @@ def cron_import_sale_order(self): self.search([]).import_sale_order() @api.multi - def import_medical_medicament(self): - self._import_from_date('carepoint.medical.medicament', - 'import_medicaments_from_date') + def import_carepoint_item(self): + self._import_from_date('carepoint.carepoint.item', + 'import_items_from_date') return True @api.multi diff --git a/connector_carepoint/models/carepoint_item.py b/connector_carepoint/models/carepoint_item.py new file mode 100644 index 0000000..167bccf --- /dev/null +++ b/connector_carepoint/models/carepoint_item.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +# Copyright 2015-2016 LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +from openerp import models, fields, api +from openerp.addons.connector.unit.mapper import (mapping, + only_create, + changed_by, + ExportMapper, + ) +from ..unit.backend_adapter import CarepointCRUDAdapter +from ..unit.mapper import CarepointImportMapper, trim +from ..backend import carepoint +from ..unit.import_synchronizer import (DelayedBatchImporter, + CarepointImporter, + ) +from ..unit.export_synchronizer import CarepointExporter + +_logger = logging.getLogger(__name__) + + +class CarepointCarepointItem(models.Model): + _name = 'carepoint.carepoint.item' + _inherit = 'carepoint.binding' + _inherits = {'carepoint.item': 'odoo_id'} + _description = 'Carepoint Item' + _cp_lib = 'item' # Name of model in Carepoint lib (snake_case) + + odoo_id = fields.Many2one( + string='Item', + comodel_name='carepoint.item', + required=True, + ondelete='restrict', + ) + store_id = fields.Many2one( + string='Store', + comodel_name='carepoint.medical.pharmacy', + readonly=True, + ) + + +class CarepointItem(models.Model): + _name = 'carepoint.item' + _inherits = {'medical.medicament': 'medicament_id'} + + medicament_id = fields.Many2one( + string='Medicament', + comodel_name='medical.medicament', + ondelete='cascade', + required=True, + ) + warehouse_id = fields.Many2one( + string='Warehouse', + comodel_name='stock.warehouse', + required=True, + ) + carepoint_bind_ids = fields.One2many( + comodel_name='carepoint.carepoint.item', + inverse_name='odoo_id', + string='Carepoint Bindings', + ) + store_on_hand = fields.Float( + compute="_compute_store_qty", + ) + store_on_order = fields.Float( + compute="_compute_store_qty", + ) + trigger_export = fields.Boolean() + + @api.one + def _compute_store_qty(self): + context_product = self.with_context(warehouse=self.warehouse_id.id) + avail = context_product._product_available()[self.id] + self.store_on_hand = avail['qty_available'] + self.store_on_order = avail['incoming_qty'] + + +@carepoint +class CarepointItemAdapter(CarepointCRUDAdapter): + _model_name = 'carepoint.carepoint.item' + + +@carepoint +class CarepointItemBatchImporter(DelayedBatchImporter): + """ Import the Carepoint Items. + For every product category in the list, a delayed job is created. + Import from a date + """ + _model_name = ['carepoint.carepoint.item'] + + +@carepoint +class CarepointItemImportMapper(CarepointImportMapper): + _model_name = 'carepoint.carepoint.item' + + direct = [ + (trim('DESCR'), 'name'), + (trim('UPCCODE'), 'barcode'), + ('add_date', 'created_at'), + ('chg_date', 'updated_at'), + ] + + @mapping + def active(self, record): + """Check if the product is active in Carepoint + and set active flag in OpenERP + status == 1 in Carepoint means active""" + return {'active': (record.get('ACTIVE_YN') == 1)} + + @mapping + def store_id(self, record): + binder = self.binder_for('carepoint.medical.pharmacy') + store_id = binder.to_odoo(record['store_id']) + return {'store_id': store_id} + + @mapping + def warehouse_id(self, record): + binder = self.binder_for('carepoint.stock.warehouse') + store_id = binder.to_odoo(record['store_id']) + return {'warehouse_id': store_id} + + @mapping + def carepoint_id(self, record): + return {'carepoint_id': record['item_id']} + + @mapping + @only_create + def odoo_id(self, record): + """ It binds on a medicament of an existing NDC """ + ndc_id = self.env['fdb.ndc'].search( + [('name', '=', record['NDC'].strip())], + limit=1, + ) + if len(ndc_id): + return {'odoo_id': ndc_id[0].medicament_id.id} + + +@carepoint +class CarepointItemImporter(CarepointImporter): + _model_name = ['carepoint.carepoint.item'] + + _base_mapper = CarepointItemImportMapper + + def _import_dependencies(self): + """ Import depends for record """ + record = self.carepoint_record + self._import_dependency(record['NDC'].strip(), + 'carepoint.fdb.ndc.cs.ext') + self._import_dependency(record['NDC'].strip(), + 'carepoint.fdb.ndc') + self._import_dependency(record['VENDOR'].strip(), + 'carepoint.carepoint.vendor') + + +@carepoint +class CarepointItemExportMapper(ExportMapper): + _model_name = 'carepoint.carepoint.item' + + direct = [ + ('name', 'DESCR'), + ('barcode', 'UPCCODE'), + ] + + @mapping + @changed_by('active') + def active_yn(self, binding): + return {'ACTIVE_YN': binding.active} + + @mapping + @changed_by('trigger_export') + def export_quantities(self, binding): + if binding.trigger_export: + binding.trigger_export = False + return {'ONHAND': binding.store_on_hand, + 'ONORDER': binding.store_on_order, + } + + +@carepoint +class CarepointItemExporter(CarepointExporter): + _model_name = ['carepoint.carepoint.item'] + _base_mapper = CarepointItemExportMapper diff --git a/connector_carepoint/models/carepoint_vendor.py b/connector_carepoint/models/carepoint_vendor.py new file mode 100644 index 0000000..7d6a69d --- /dev/null +++ b/connector_carepoint/models/carepoint_vendor.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# Copyright 2015-2016 LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +from openerp import models, fields +from openerp.addons.connector.unit.mapper import (mapping, + changed_by, + only_create, + ) +from ..unit.backend_adapter import CarepointCRUDAdapter +from ..unit.mapper import (PersonImportMapper, + PersonExportMapper, + trim, + ) +from ..backend import carepoint +from ..unit.import_synchronizer import (DelayedBatchImporter, + CarepointImporter, + ) +from ..unit.export_synchronizer import (CarepointExporter) + + +_logger = logging.getLogger(__name__) + + +class CarepointCarepointVendor(models.Model): + """ Binding Model for the Carepoint Vendor """ + _name = 'carepoint.carepoint.vendor' + _inherit = 'carepoint.binding' + _inherits = {'carepoint.vendor': 'odoo_id'} + _description = 'Carepoint Vendor' + _cp_lib = 'VEND' # Name of model in Carepoint lib (snake_case) + + odoo_id = fields.Many2one( + comodel_name='carepoint.vendor', + string='Vendor', + required=True, + ondelete='cascade' + ) + backend_id = fields.Many2one( + comodel_name='carepoint.backend', + string='Carepoint Backend', + store=True, + readonly=True, + # override 'carepoint.binding', can't be INSERTed if True: + required=False, + ) + created_at = fields.Date('Created At (on Carepoint)') + updated_at = fields.Date('Updated At (on Carepoint)') + + +class CarepointVendor(models.Model): + """ Adds the ``one2many`` relation to the Carepoint bindings + (``carepoint_bind_ids``) + """ + _name = 'carepoint.vendor' + _inherits = {'res.partner': 'partner_id'} + + partner_id = fields.Many2one( + string='Partner', + comodel_name='res.partner', + ondelete='cascade', + required=True, + ) + carepoint_bind_ids = fields.One2many( + comodel_name='carepoint.carepoint.vendor', + inverse_name='odoo_id', + string='Carepoint Bindings', + ) + + +@carepoint +class CarepointVendorAdapter(CarepointCRUDAdapter): + """ Backend Adapter for the Carepoint Vendor """ + _model_name = 'carepoint.carepoint.vendor' + + +@carepoint +class CarepointVendorBatchImporter(DelayedBatchImporter): + """ Import the Carepoint Vendors. + For every patient in the list, a delayed job is created. + """ + _model_name = ['carepoint.carepoint.vendor'] + + +@carepoint +class CarepointVendorImportMapper(PersonImportMapper): + _model_name = 'carepoint.carepoint.vendor' + + direct = [ + (trim('COMPANY'), 'name'), + (trim('ADDR1'), 'street'), + (trim('ADDR2'), 'street2'), + (trim('CITY'), 'city'), + (trim('ZIP'), 'zip'), + (trim('FEDID'), 'ref'), + (trim('phone'), 'phone'), + (trim('fax'), 'fax'), + ('add_date', 'created_at'), + ('chg_date', 'updated_at'), + ] + + @mapping + @only_create + def customer(self, record): + return {'customer': False} + + @mapping + def supplier(self, record): + return {'supplier': True} + + @mapping + def is_company(self, record): + return {'is_company': True} + + @mapping + def state_id(self, record): + state_id = self.env['res.country.state'].search( + [('code', '=', record['STATE'].upper())], + limit=1, + ) + if len(state_id): + return { + 'state_id': state_id[0].id, + 'country_id': state_id[0].country_id.id, + } + + @mapping + def carepoint_id(self, record): + return {'carepoint_id': record['ID']} + + @mapping + @only_create + def odoo_id(self, record): + """ It binds on vendor of existing name """ + vendor_id = self.env['res.partner'].search( + [('name', 'ilike', record['COMPANY'].strip())], + limit=1, + ) + if len(vendor_id): + return {'odoo_id': vendor_id[0].id} + + +@carepoint +class CarepointVendorImporter(CarepointImporter): + _model_name = ['carepoint.carepoint.vendor'] + _base_mapper = CarepointVendorImportMapper + + +@carepoint +class CarepointVendorExportMapper(PersonExportMapper): + _model_name = 'carepoint.carepoint.vendor' + + direct = [ + ('name', 'COMPANY'), + ('street', 'ADDR1'), + ('street2', 'ADDR2'), + ('city', 'CITY'), + ('zip', 'ZIPCODE'), + ('ref', 'FEDID'), + ('phone', 'PHONE'), + ('fax', 'FAX'), + ] + + @mapping + @changed_by('state_id') + def state(self, record): + return {'STATE': record.state_id.code} + + +@carepoint +class CarepointVendorExporter(CarepointExporter): + _model_name = ['carepoint.carepoint.vendor'] + _base_mapper = CarepointVendorExportMapper diff --git a/connector_carepoint/models/medical_medicament.py b/connector_carepoint/models/medical_medicament.py deleted file mode 100644 index bc8ab9a..0000000 --- a/connector_carepoint/models/medical_medicament.py +++ /dev/null @@ -1,400 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2015-2016 LasLabs Inc. -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -import logging -from openerp import models, fields -from openerp.addons.connector.unit.mapper import (mapping, - only_create, - ) -from ..unit.backend_adapter import CarepointCRUDAdapter -from ..unit.mapper import CarepointImportMapper -from ..backend import carepoint -from ..unit.import_synchronizer import (DelayedBatchImporter, - CarepointImporter, - ) - -_logger = logging.getLogger(__name__) - - -class CarepointMedicalMedicament(models.Model): - _name = 'carepoint.medical.medicament' - _inherit = 'carepoint.binding' - _inherits = {'medical.medicament': 'odoo_id'} - _description = 'Carepoint Medicament' - _cp_lib = 'item' # Name of model in Carepoint lib (snake_case) - - odoo_id = fields.Many2one( - string='Medicament', - comodel_name='medical.medicament', - required=True, - ondelete='restrict', - ) - store_ids = fields.Many2many( - string='Stores', - comodel_name='carepoint.medical.pharmacy', - readonly=True, - ) - created_at = fields.Date('Created At (on Carepoint)') - updated_at = fields.Date('Updated At (on Carepoint)') - manage_stock = fields.Selection( - selection=[('use_default', 'Use Default Config'), - ('no', 'Do Not Manage Stock'), - ('yes', 'Manage Stock')], - string='Manage Stock Level', - default='use_default', - required=True, - ) - backorders = fields.Selection( - selection=[('use_default', 'Use Default Config'), - ('no', 'No Sell'), - ('yes', 'Sell Quantity < 0'), - ('yes-and-notification', 'Sell Quantity < 0 and ' - 'Use Customer Notification')], - string='Manage Inventory Backorders', - default='use_default', - required=True, - ) - carepoint_qty = fields.Float( - string='Computed Quantity', - help="Last computed quantity to send on Carepoint." - ) - no_stock_sync = fields.Boolean( - string='No Stock Synchronization', - required=False, - help="Check this to exclude the product " - "from stock synchronizations.", - ) - - RECOMPUTE_QTY_STEP = 1000 # products at a time - - # @api.multi - # def recompute_carepoint_qty(self): - # """ Check if the quantity in the stock location configured - # on the backend has changed since the last export. - # If it has changed, write the updated quantity on `carepoint_qty`. - # The write on `carepoint_qty` will trigger an `on_record_write` - # event that will create an export job. - # It groups the products by backend to avoid to read the backend - # informations for each product. - # """ - # # group products by backend - # backends = defaultdict(self.browse) - # for product in self: - # backends[product.backend_id] |= product - # - # for backend, products in backends.iteritems(): - # self._recompute_carepoint_qty_backend(backend, products) - # return True - # - # @api.multi - # def _recompute_carepoint_qty_backend(self, backend, products, - # read_fields=None): - # """ Recompute the products quantity for one backend. - # If field names are passed in ``read_fields`` (as a list), they - # will be read in the product that is used in - # :meth:`~._carepoint_qty`. - # """ - # if backend.product_stock_field_id: - # stock_field = backend.product_stock_field_id.name - # else: - # stock_field = 'virtual_available' - # - # location = backend.warehouse_id.lot_stock_id - # - # product_fields = ['carepoint_qty', stock_field] - # if read_fields: - # product_fields += read_fields - # - # self_with_location = self.with_context(location=location.id) - # for chunk_ids in chunks(products.ids, self.RECOMPUTE_QTY_STEP): - # records = self_with_location.browse(chunk_ids) - # for product in records.read(fields=product_fields): - # new_qty = self._carepoint_qty( - # product, backend, location, stock_field - # ) - # if new_qty != product['carepoint_qty']: - # self.browse(product['id']).carepoint_qty = new_qty - # - # @api.multi - # def _carepoint_qty(self, product, backend, location, stock_field): - # """ Return the current quantity for one product. - # Can be inherited to change the way the quantity is computed, - # according to a backend / location. - # If you need to read additional fields on the product, see the - # ``read_fields`` argument of - # :meth:`~._recompute_carepoint_qty_backend` - # """ - # return product[stock_field] - - -class MedicalMedicament(models.Model): - _inherit = 'medical.medicament' - - carepoint_bind_ids = fields.One2many( - comodel_name='carepoint.medical.medicament', - inverse_name='odoo_id', - string='Carepoint Bindings', - ) - - -@carepoint -class MedicalMedicamentAdapter(CarepointCRUDAdapter): - _model_name = 'carepoint.medical.medicament' - - # def get_images(self, id, storeview_id=None): - # return self._call('product_media.list', - # [int(id), storeview_id, 'id']) - # - # def read_image(self, id, image_name, storeview_id=None): - # return self._call('product_media.info', - # [int(id), image_name, storeview_id, 'id']) - # - # def update_inventory(self, id, data): - # # product_stock.update is too slow - # return self._call('oerp_cataloginventory_stock_item.update', - # [int(id), data]) - - -@carepoint -class MedicamentBatchImporter(DelayedBatchImporter): - """ Import the Carepoint Medicaments. - For every product category in the list, a delayed job is created. - Import from a date - """ - _model_name = ['carepoint.medical.medicament'] - -# -# @carepoint -# class CatalogImageImporter(Importer): -# """ Import images for a record. -# Usually called from importers, in ``_after_import``. -# For instance from the products importer. -# """ -# -# _model_name = ['carepoint.medical.medicament', -# ] -# -# def _get_images(self, storeview_id=None): -# return self.backend_adapter.get_images( -# self.carepoint_id, storeview_id) -# -# def _sort_images(self, images): -# """ Returns a list of images sorted by their priority. -# An image with the 'image' type is the the primary one. -# The other images are sorted by their position. -# The returned list is reversed, the items at the end -# of the list have the higher priority. -# """ -# if not images: -# return {} -# # place the images where the type is 'image' first then -# # sort them by the reverse priority (last item of the list has -# # the the higher priority) -# -# def priority(image): -# primary = 'image' in image['types'] -# try: -# position = int(image['position']) -# except ValueError: -# position = sys.maxint -# return (primary, -position) -# return sorted(images, key=priority) -# -# def _get_binary_image(self, image_data): -# url = image_data['url'].encode('utf8') -# try: -# request = urllib2.Request(url) -# if self.backend_record.auth_basic_username \ -# and self.backend_record.auth_basic_password: -# base64string = base64.encodestring( -# '%s:%s' % (self.backend_record.auth_basic_username, -# self.backend_record.auth_basic_password)) -# request.add_header( -# "Authorization", "Basic %s" % base64string) -# binary = urllib2.urlopen(request) -# except urllib2.HTTPError as err: -# if err.code == 404: -# # the image is just missing, we skip it -# return -# else: -# # we don't know why we couldn't download the image -# # so we propagate the error, the import will fail -# # and we have to check why it couldn't be accessed -# raise -# else: -# return binary.read() -# -# def run(self, carepoint_id, binding_id): -# self.carepoint_id = carepoint_id -# images = self._get_images() -# images = self._sort_images(images) -# binary = None -# while not binary and images: -# binary = self._get_binary_image(images.pop()) -# if not binary: -# return -# model = self.model.with_context(connector_no_export=True) -# binding = model.browse(binding_id) -# binding.write({'image': base64.b64encode(binary)}) - - -@carepoint -class MedicamentImportMapper(CarepointImportMapper): - _model_name = 'carepoint.medical.medicament' - direct = [ - ('DESCR', 'name'), - ('SKU', 'sku'), - ('UPCCODE', 'ean13'), - ('add_date', 'created_at'), - ('chg_date', 'updated_at'), - ] - - # @mapping - # @only_create - # def ndc_id(self, record): - # return {'ndc_ids': [(0, 0, {'name': record['NDC']})]} - - @mapping - @only_create - def route_form_and_ndc_ids(self, record): - binder = self.binder_for('carepoint.fdb.ndc.cs.ext') - ndc_id = binder.to_odoo(record['NDC']) - ndc_id = self.env['fdb.ndc.cs.ext'].browse(ndc_id) - vals = { - 'drug_route_id': ndc_id.route_id.id, - 'drug_form_id': ndc_id.form_id.id, - } - return vals - - @mapping - def is_active(self, record): - """Check if the product is active in Carepoint - and set active flag in OpenERP - status == 1 in Carepoint means active""" - return {'active': (record.get('ACTIVE_YN') == 1)} - - @mapping - def price(self, record): - return {'list_price': record.get('COST', 0.0)} - - @mapping - def store_ids(self, record): - # @TODO: somehow combine the products for stores - return {'store_ids': [record['store_id']]} - - @mapping - def carepoint_id(self, record): - return {'carepoint_id': record['item_id']} - - -@carepoint -class MedicamentImporter(CarepointImporter): - _model_name = ['carepoint.medical.medicament'] - - _base_mapper = MedicamentImportMapper - - def _import_dependencies(self): - """ Import depends for record """ - record = self.carepoint_record - self._import_dependency(record['NDC'], - 'carepoint.fdb.ndc.cs.ext') - - def _must_skip(self): - """ Hook called right after we read the data from the backend. - If the method returns a message giving a reason for the - skipping, the import will be interrupted and the message - recorded in the job (if the import is called directly by the - job, not by dependencies). - If it returns None, the import will continue normally. - :returns: None | str | unicode - """ - - def _validate_data(self, data): - """ Check if the values to import are correct - Pro-actively check before the ``_create`` or - ``_update`` if some fields are missing or invalid - Raise `InvalidDataError` - """ - - def _after_import(self, binding): - """ Hook called at the end of the import """ - self._import_dependency(self.carepoint_record['ndc'].strip(), - 'carepoint.fdb.ndc') - # translation_importer = self.unit_for(TranslationImporter) - # translation_importer.run(self.carepoint_id, binding.id, - # mapper_class=MedicamentImportMapper) - # image_importer = self.unit_for(CatalogImageImporter) - # image_importer.run(self.carepoint_id, binding.id) - - -# @carepoint -# class MedicamentInventoryExporter(Exporter): -# _model_name = ['carepoint.medical.medicament'] -# -# _map_backorders = {'use_default': 0, -# 'no': 0, -# 'yes': 1, -# 'yes-and-notification': 2, -# } -# -# def _get_data(self, product, fields): -# result = {} -# if 'carepoint_qty' in fields: -# result.update({ -# 'qty': product.carepoint_qty, -# # put the stock availability to "out of stock" -# 'is_in_stock': int(product.carepoint_qty > 0) -# }) -# if 'manage_stock' in fields: -# manage = product.manage_stock -# result.update({ -# 'manage_stock': int(manage == 'yes'), -# 'use_config_manage_stock': int(manage == 'use_default'), -# }) -# if 'backorders' in fields: -# backorders = product.backorders -# result.update({ -# 'backorders': self._map_backorders[backorders], -# 'use_config_backorders': int(backorders == 'use_default'), -# }) -# return result -# -# def run(self, binding_id, fields): -# """ Export the product inventory to Carepoint """ -# product = self.model.browse(binding_id) -# carepoint_id = self.binder.to_backend(product.id) -# data = self._get_data(product, fields) -# self.backend_adapter.update_inventory(carepoint_id, data) -# -# -# # fields which should not trigger an export of the products -# # but an export of their inventory -# INVENTORY_FIELDS = ('manage_stock', -# 'backorders', -# 'carepoint_qty', -# ) -# -# -# @on_record_write(model_names='carepoint.medical.medicament') -# def carepoint_product_modified(session, model_name, record_id, vals): -# if session.context.get('connector_no_export'): -# return -# if session.env[model_name].browse(record_id).no_stock_sync: -# return -# inventory_fields = list(set(vals).intersection(INVENTORY_FIELDS)) -# if inventory_fields: -# export_product_inventory.delay(session, model_name, -# record_id, fields=inventory_fields, -# priority=20) -# -# -# @job(default_channel='root.carepoint') -# @related_action(action=unwrap_binding) -# def export_product_inventory(session, model_name, record_id, fields=None): -# """ Export the inventory configuration and quantity of a product. """ -# product = session.env[model_name].browse(record_id) -# backend_id = product.backend_id.id -# env = get_environment(session, model_name, backend_id) -# inventory_exporter = env.get_connector_unit(MedicamentInventoryExporter) -# return inventory_exporter.run(record_id, fields) diff --git a/connector_carepoint/models/medical_pharmacy.py b/connector_carepoint/models/medical_pharmacy.py index e327076..b082f23 100644 --- a/connector_carepoint/models/medical_pharmacy.py +++ b/connector_carepoint/models/medical_pharmacy.py @@ -31,6 +31,11 @@ class CarepointMedicalPharmacy(models.Model): required=True, ondelete='cascade' ) + warehouse_id = fields.Many2one( + string='Warehouse', + comodel_name='stock.warehouse', + required=True, + ) class MedicalPharmacy(models.Model): @@ -92,6 +97,12 @@ def odoo_id(self, record): def parent_id(self, record): return {'parent_id': self.backend_record.company_id.partner_id.id} + @mapping + def warehouse_id(self, record): + binder = self.binder_for('carepoint.stock.warehouse') + warehouse_id = binder.to_odoo(record['store_id']) + return {'warehouse_id': warehouse_id} + @mapping def carepoint_id(self, record): return {'carepoint_id': record['store_id']} @@ -101,3 +112,7 @@ def carepoint_id(self, record): class MedicalPharmacyImporter(CarepointImporter): _model_name = ['carepoint.medical.pharmacy'] _base_mapper = MedicalPharmacyImportMapper + + def _import_dependencies(self): + self._import_dependency(self.carepoint_record['store_id'], + 'carepoint.stock.warehouse') diff --git a/connector_carepoint/models/stock_warehouse.py b/connector_carepoint/models/stock_warehouse.py new file mode 100644 index 0000000..5af9d73 --- /dev/null +++ b/connector_carepoint/models/stock_warehouse.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# Copyright 2015-2016 LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +from openerp import models, fields +from openerp.addons.connector.unit.mapper import (mapping, + only_create, + ) +from ..unit.backend_adapter import CarepointCRUDAdapter +from ..backend import carepoint +from ..unit.mapper import PartnerImportMapper, trim +from ..unit.import_synchronizer import (DelayedBatchImporter, + CarepointImporter, + ) + +_logger = logging.getLogger(__name__) + + +class CarepointStockWarehouse(models.Model): + """ Binding Model for the Carepoint Warehouse """ + _name = 'carepoint.stock.warehouse' + _inherit = 'carepoint.binding' + _inherits = {'stock.warehouse': 'odoo_id'} + _description = 'Carepoint Warehouse' + _cp_lib = 'store' # Name of model in Carepoint lib (snake_case) + + odoo_id = fields.Many2one( + comodel_name='stock.warehouse', + string='Company', + required=True, + ondelete='cascade' + ) + + +class StockWarehouse(models.Model): + """ Adds the ``one2many`` relation to the Carepoint bindings + (``carepoint_bind_ids``) + """ + _inherit = 'stock.warehouse' + + carepoint_bind_ids = fields.One2many( + comodel_name='carepoint.stock.warehouse', + inverse_name='odoo_id', + string='Carepoint Bindings', + ) + + +@carepoint +class StockWarehouseAdapter(CarepointCRUDAdapter): + """ Backend Adapter for the Carepoint Store """ + _model_name = 'carepoint.stock.warehouse' + + +@carepoint +class StockWarehouseBatchImporter(DelayedBatchImporter): + """ Import the Carepoint Stores. + For every company in the list, a delayed job is created. + """ + _model_name = ['carepoint.stock.warehouse'] + + +@carepoint +class StockWarehouseImportMapper(PartnerImportMapper): + _model_name = 'carepoint.stock.warehouse' + + direct = [ + (trim('name'), 'name'), + ] + + @mapping + @only_create + def code(self, record): + return {'code': record['name'].strip()} + + @mapping + def is_pharmacy(self, record): + return {'is_pharmacy': True} + + @mapping + def partner_id_company_id(self, record): + binder = self.binder_for('carepoint.medical.pharmacy') + pharmacy_id = binder.to_odoo(record['store_id'], browse=True) + return { + 'company_id': pharmacy_id.company_id.id, + 'partner_id': pharmacy_id.partner_id.id, + } + + @mapping + @only_create + def route_ids(self, record): + """ It returns the RX & OTC route ids """ + module = 'medical_prescription_sale_stock' + rx_route_id = self.env.ref( + '%s.route_warehouse0_prescription' % module + ) + otc_route_id = self.env.ref( + '%s.route_warehouse0_otc' % module + ) + return { + 'route_ids': [(6, 0, [rx_route_id.id, otc_route_id.id])], + 'prescription_route_id': rx_route_id.id, + 'otc_route_id': otc_route_id.id, + } + + @mapping + def carepoint_id(self, record): + return {'carepoint_id': record['store_id']} + + +@carepoint +class StockWarehouseImporter(CarepointImporter): + _model_name = ['carepoint.stock.warehouse'] + _base_mapper = StockWarehouseImportMapper diff --git a/connector_carepoint/security/ir.model.access.csv b/connector_carepoint/security/ir.model.access.csv index 03200af..9d78a53 100644 --- a/connector_carepoint/security/ir.model.access.csv +++ b/connector_carepoint/security/ir.model.access.csv @@ -5,3 +5,5 @@ access_carepoint_address_patient_medical_user,access_carepoint_address_patient_m access_carepoint_address_pharmacy_medical_user,access_carepoint_address_pharmacy_medical_user,connector_carepoint.model_carepoint_address_pharmacy,medical.group_medical_user,1,0,0,0 access_carepoint_account_medical_user,access_carepoint_account_medical_user,connector_carepoint.model_carepoint_account,medical.group_medical_user,1,0,0,0 access_carepoint_state_medical_user,access_carepoint_state_medical_user,connector_carepoint.model_carepoint_state,medical.group_medical_user,1,0,0,0 +access_carepoint_vendor_medical_user,access_carepoint_vendor_medical_user,connector_carepoint.model_carepoint_vendor,medical.group_medical_user,1,0,0,0 +access_carepoint_item_medical_user,access_carepoint_item_medical_user,connector_carepoint.model_carepoint_item,medical.group_medical_user,1,0,0,0 diff --git a/connector_carepoint/tests/models/__init__.py b/connector_carepoint/tests/models/__init__.py index 553daf0..30f6bfb 100644 --- a/connector_carepoint/tests/models/__init__.py +++ b/connector_carepoint/tests/models/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2015-2016 LasLabs Inc. +# Copyright 2015-TODAY LasLabs Inc. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import test_medical_pharmacy @@ -11,3 +11,6 @@ from . import test_sale_order_line from . import test_sale_order from . import test_stock_picking +from . import test_stock_warehouse +from . import test_carepoint_item +from . import test_carepoint_vendor diff --git a/connector_carepoint/tests/models/test_carepoint_item.py b/connector_carepoint/tests/models/test_carepoint_item.py new file mode 100644 index 0000000..6019fcf --- /dev/null +++ b/connector_carepoint/tests/models/test_carepoint_item.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +# Copyright 2015-2016 LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import mock + +from openerp.addons.connector_carepoint.models import carepoint_item + +from ..common import SetUpCarepointBase + + +class EndTestException(Exception): + pass + + +class CarepointItemTestBase(SetUpCarepointBase): + + def setUp(self): + super(CarepointItemTestBase, self).setUp() + self.model = 'carepoint.carepoint.item' + self.mock_env = self.get_carepoint_helper( + self.model + ) + self.record = { + 'ACTIVE_YN': 1, + 'store_id': 2, + 'item_id': 3, + 'NDC': ' ndc ', + 'VENDOR': ' 0001 ', + } + + +class TestCarepointItemImportMapper(CarepointItemTestBase): + + def setUp(self): + super(TestCarepointItemImportMapper, self).setUp() + self.Unit = carepoint_item.CarepointItemImportMapper + self.unit = self.Unit(self.mock_env) + + def test_store_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.store_id(self.record) + self.unit.binder_for.assert_called_once_with( + 'carepoint.medical.pharmacy' + ) + + def test_store_id_to_odoo(self): + """ It should get Odoo record for store """ + with mock.patch.object(self.unit, 'binder_for'): + self.unit.binder_for().to_odoo.side_effect = EndTestException + with self.assertRaises(EndTestException): + self.unit.store_id(self.record) + self.unit.binder_for().to_odoo.assert_called_once_with( + self.record['store_id'], + ) + + def test_store_id_return(self): + """ It should return formatted store_id """ + with mock.patch.object(self.unit, 'binder_for'): + res = self.unit.store_id(self.record) + expect = self.unit.binder_for().to_odoo() + self.assertDictEqual({'store_id': expect}, res) + + def test_warehouse_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.warehouse_id(self.record) + self.unit.binder_for.assert_called_once_with( + 'carepoint.stock.warehouse' + ) + + def test_warehouse_id_to_odoo(self): + """ It should get Odoo record for store """ + with mock.patch.object(self.unit, 'binder_for'): + self.unit.binder_for().to_odoo.side_effect = EndTestException + with self.assertRaises(EndTestException): + self.unit.warehouse_id(self.record) + self.unit.binder_for().to_odoo.assert_called_once_with( + self.record['store_id'], + ) + + def test_warehouse_id_return(self): + """ It should return formatted warehouse_id """ + with mock.patch.object(self.unit, 'binder_for'): + res = self.unit.warehouse_id(self.record) + expect = self.unit.binder_for().to_odoo() + self.assertDictEqual({'warehouse_id': expect}, res) + + def test_active_yes(self): + """ It should return correct vals """ + res = self.unit.active(self.record) + self.assertDictEqual({'active': True}, res) + + def test_active_no(self): + """ It should return correct vals """ + res = self.unit.active({'ACTIVE_YN': 0}) + self.assertDictEqual({'active': False}, res) + + def test_odoo_id_search(self): + """ It should search for NDC """ + with mock.patch.object(self.unit.session, 'env') as env: + self.unit.odoo_id(self.record) + env[''].search.assert_called_once_with( + [('name', '=', self.record['NDC'].strip())], + limit=1, + ) + + def test_odoo_id_return(self): + """ It should search for NDC """ + with mock.patch.object(self.unit.session, 'env') as env: + expect = [mock.MagicMock()] + env[''].search.return_value = expect + res = self.unit.odoo_id(self.record) + self.assertDictEqual( + {'odoo_id': expect[0].medicament_id.id}, + res, + ) + + def test_carepoint_id(self): + """ It should return correct attribute """ + res = self.unit.carepoint_id(self.record) + expect = {'carepoint_id': self.record['item_id']} + self.assertDictEqual(expect, res) + + +class TestCarepointItemImporter(CarepointItemTestBase): + + def setUp(self): + super(TestCarepointItemImporter, self).setUp() + self.Unit = carepoint_item.CarepointItemImporter + self.unit = self.Unit(self.mock_env) + self.unit.carepoint_record = self.record + + def test_import_dependencies(self): + """ It should import all depedencies """ + with mock.patch.object(self.unit, '_import_dependency') as mk: + self.unit._import_dependencies() + mk.assert_has_calls([ + mock.call( + self.record['NDC'].strip(), + 'carepoint.fdb.ndc.cs.ext', + ), + mock.call( + self.record['NDC'].strip(), + 'carepoint.fdb.ndc', + ), + mock.call( + self.record['VENDOR'].strip(), + 'carepoint.carepoint.vendor' + ), + ]) + + +class TestCarepointItemExportMapper(CarepointItemTestBase): + + def setUp(self): + super(TestCarepointItemExportMapper, self).setUp() + self.Unit = carepoint_item.CarepointItemExportMapper + self.unit = self.Unit(self.mock_env) + self.record = mock.MagicMock() + + def test_active_yn(self): + """ It should return correct vals """ + res = self.unit.active_yn(self.record) + self.assertDictEqual({'ACTIVE_YN': self.record.active}, res) + + def test_export_quantities_on_trigger(self): + """ It should return correct vals on trigger """ + self.record.trigger_export = True + res = self.unit.export_quantities(self.record) + expect = { + 'ONHAND': self.record.store_on_hand, + 'ONORDER': self.record.store_on_order, + } + self.assertDictEqual(expect, res) + + def test_export_quantities_unset_trigger(self): + """ It should unsert trigger_export """ + self.record.trigger_export = True + self.unit.export_quantities(self.record) + self.assertFalse(self.record.trigger_export) + + def test_export_quantities_no_trigger(self): + """ It should not return anytying when no trigger_export """ + self.record.trigger_export = False + res = self.unit.export_quantities(self.record) + self.assertEqual(None, res) diff --git a/connector_carepoint/tests/models/test_carepoint_vendor.py b/connector_carepoint/tests/models/test_carepoint_vendor.py new file mode 100644 index 0000000..f36d35b --- /dev/null +++ b/connector_carepoint/tests/models/test_carepoint_vendor.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +# Copyright 2015-2016 LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import mock + +from openerp.addons.connector_carepoint.models import carepoint_vendor + +from ..common import SetUpCarepointBase + + +class EndTestException(Exception): + pass + + +class CarepointVendorTestBase(SetUpCarepointBase): + + def setUp(self): + super(CarepointVendorTestBase, self).setUp() + self.model = 'carepoint.carepoint.vendor' + self.mock_env = self.get_carepoint_helper( + self.model + ) + self.record = { + 'COMPANY': ' Test Vendor ', + 'STATE': 'nv', + 'ID': 123, + } + + +class TestCarepointVendorImportMapper(CarepointVendorTestBase): + + def setUp(self): + super(TestCarepointVendorImportMapper, self).setUp() + self.Unit = carepoint_vendor.CarepointVendorImportMapper + self.unit = self.Unit(self.mock_env) + + def test_customer(self): + """ It should return proper vals """ + res = self.unit.customer(self.record) + self.assertDictEqual({'customer': False}, res) + + def test_supplier(self): + """ It should return proper vals """ + res = self.unit.supplier(self.record) + self.assertDictEqual({'supplier': True}, res) + + def test_is_company(self): + """ It should return proper vals """ + res = self.unit.is_company(self.record) + self.assertDictEqual({'is_company': True}, res) + + def test_state_id_search(self): + """ It should search for NDC """ + with mock.patch.object(self.unit.session, 'env') as env: + self.unit.state_id(self.record) + env[''].search.assert_called_once_with( + [('code', '=', self.record['STATE'].upper())], + limit=1, + ) + + def test_state_id_return(self): + """ It should search for NDC """ + with mock.patch.object(self.unit.session, 'env') as env: + expect = mock.MagicMock() + env[''].search.return_value = [expect] + res = self.unit.state_id(self.record) + self.assertDictEqual( + {'state_id': expect.id, + 'country_id': expect.country_id.id}, + res, + ) + + def test_carepoint_id(self): + """ It should return proper vals """ + res = self.unit.carepoint_id(self.record) + self.assertDictEqual({'carepoint_id': self.record['ID']}, res) + + def test_odoo_id_search(self): + """ It should search for NDC """ + with mock.patch.object(self.unit.session, 'env') as env: + self.unit.odoo_id(self.record) + env[''].search.assert_called_once_with( + [('name', 'ilike', self.record['COMPANY'].strip())], + limit=1, + ) + + def test_odoo_id_return(self): + """ It should search for NDC """ + with mock.patch.object(self.unit.session, 'env') as env: + expect = [mock.MagicMock()] + env[''].search.return_value = expect + res = self.unit.odoo_id(self.record) + self.assertDictEqual( + {'odoo_id': expect[0].id}, + res, + ) + + +class TestCarepointVendorExportMapper(CarepointVendorTestBase): + + def setUp(self): + super(TestCarepointVendorExportMapper, self).setUp() + self.Unit = carepoint_vendor.CarepointVendorExportMapper + self.unit = self.Unit(self.mock_env) + self.record = mock.MagicMock() + + def state(self): + """ It should return correct vals """ + res = self.unit.state(self.record) + self.assertDictEqual({'STATE': self.record.state_id.code}, res) diff --git a/connector_carepoint/tests/models/test_fdb_pem_mogc.py b/connector_carepoint/tests/models/test_fdb_pem_mogc.py deleted file mode 100644 index 8c94d59..0000000 --- a/connector_carepoint/tests/models/test_fdb_pem_mogc.py +++ /dev/null @@ -1,102 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2015-2016 LasLabs Inc. -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -import mock - -from openerp.addons.connector_carepoint.models import ( - sale_order_line -) - -from ..common import SetUpCarepointBase - - -model = 'openerp.addons.connector_carepoint.models.%s' % ( - 'sale_order_line' -) - - -class EndTestException(Exception): - pass - - -class SaleOrderLineTestBase(SetUpCarepointBase): - - def setUp(self): - super(SaleOrderLineTestBase, self).setUp() - self.model = 'carepoint.sale.order.line' - self.mock_env = self.get_carepoint_helper( - self.model - ) - - @property - def record(self): - """ Model record fixture """ - return { - 'gcn_seqno': 1, - 'pemono': 2, - 'pemono_sn': 3, - } - - -class TestSaleOrderLineImportMapper(SaleOrderLineTestBase): - - def setUp(self): - super(TestSaleOrderLineImportMapper, self).setUp() - self.Unit = sale_order_line.SaleOrderLineImportMapper - self.unit = self.Unit(self.mock_env) - - def test_carepoint_id(self): - """ It should return correct attribute """ - expect = {'carepoint_id': self.record['gcn_seqno']} - res = self.unit.carepoint_id(self.record) - self.assertDictEqual(expect, res) - - def test_gcn_id_get_binder(self): - """ It should get binder for record type """ - with mock.patch.object(self.unit, 'binder_for'): - self.unit.binder_for.side_effect = EndTestException - with self.assertRaises(EndTestException): - self.unit.gcn_id(self.record) - self.unit.binder_for.assert_called_once_with( - 'carepoint.fdb.gcn' - ) - - def test_gcn_id_to_odoo(self): - """ It should get Odoo record for binding """ - with mock.patch.object(self.unit, 'binder_for'): - self.unit.binder_for().to_odoo.side_effect = EndTestException - with self.assertRaises(EndTestException): - self.unit.gcn_id(self.record) - self.unit.binder_for().to_odoo.assert_called_once_with( - self.record['gcn_seqno'], - ) - - def test_gcn_id_return(self): - """ It should return proper vals dict """ - with mock.patch.object(self.unit, 'binder_for'): - gcn_id = self.unit.binder_for().to_odoo() - expect = {'gcn_id': gcn_id} - res = self.unit.gcn_id(self.record) - self.assertDictEqual(expect, res) - - -class TestSaleOrderLineImporter(SaleOrderLineTestBase): - - def setUp(self): - super(TestSaleOrderLineImporter, self).setUp() - self.Unit = sale_order_line.\ - SaleOrderLineImporter - self.unit = self.Unit(self.mock_env) - self.unit.carepoint_record = self.record - - def test_import_dependencies(self): - """ It should import all depedencies """ - with mock.patch.object(self.unit, '_import_dependency') as mk: - self.unit._import_dependencies() - mk.assert_has_calls([ - mock.call( - self.record['gcn_seqno'], - 'carepoint.fdb.gcn', - ), - ]) diff --git a/connector_carepoint/tests/models/test_medical_pharmacy.py b/connector_carepoint/tests/models/test_medical_pharmacy.py index 1c027fc..dc8e2cd 100644 --- a/connector_carepoint/tests/models/test_medical_pharmacy.py +++ b/connector_carepoint/tests/models/test_medical_pharmacy.py @@ -2,25 +2,38 @@ # Copyright 2015-2016 LasLabs Inc. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import mock + from openerp.addons.connector_carepoint.models import medical_pharmacy from ..common import SetUpCarepointBase -class TestMedicalPharmacy(SetUpCarepointBase): +class EndTestException(Exception): + pass + + +class MedicalPharmacyTestBase(SetUpCarepointBase): def setUp(self): - super(TestMedicalPharmacy, self).setUp() - self.Unit = medical_pharmacy.MedicalPharmacyImportMapper + super(MedicalPharmacyTestBase, self).setUp() self.model = 'carepoint.medical.pharmacy' self.mock_env = self.get_carepoint_helper( self.model ) - self.unit = self.Unit(self.mock_env) self.record = { 'name': 'Test Pharmacy', + 'store_id': 123, } + +class TestMedicalPharmacyImportMapper(MedicalPharmacyTestBase): + + def setUp(self): + super(TestMedicalPharmacyImportMapper, self).setUp() + self.Unit = medical_pharmacy.MedicalPharmacyImportMapper + self.unit = self.Unit(self.mock_env) + def test_odoo_id(self): """ It should return odoo_id of pharmacies with same name """ expect = self.env[self.model.replace('carepoint.', '')].create( @@ -39,6 +52,33 @@ def test_parent_id(self): } self.assertDictEqual(expect, res) + def test_warehouse_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.warehouse_id(self.record) + self.unit.binder_for.assert_called_once_with( + 'carepoint.stock.warehouse' + ) + + def test_warehouse_id_to_odoo(self): + """ It should get Odoo record for rx """ + with mock.patch.object(self.unit, 'binder_for'): + self.unit.binder_for().to_odoo.side_effect = EndTestException + with self.assertRaises(EndTestException): + self.unit.warehouse_id(self.record) + self.unit.binder_for().to_odoo.assert_called_once_with( + self.record['store_id'], + ) + + def test_warehouse_id_return(self): + """ It should return formatted warehouse_id """ + with mock.patch.object(self.unit, 'binder_for'): + res = self.unit.warehouse_id(self.record) + expect = self.unit.binder_for().to_odoo() + self.assertDictEqual({'warehouse_id': expect}, res) + def test_carepoint_id(self): """ It should return correct attribute """ expect = 6789 @@ -46,3 +86,23 @@ def test_carepoint_id(self): res = self.unit.carepoint_id(self.record) expect = {'carepoint_id': expect} self.assertDictEqual(expect, res) + + +class TestMedicalPharmacyImporter(MedicalPharmacyTestBase): + + def setUp(self): + super(TestMedicalPharmacyImporter, self).setUp() + self.Unit = medical_pharmacy.MedicalPharmacyImporter + self.unit = self.Unit(self.mock_env) + self.unit.carepoint_record = self.record + + def test_import_dependencies(self): + """ It should import all depedencies """ + with mock.patch.object(self.unit, '_import_dependency') as mk: + self.unit._import_dependencies() + mk.assert_has_calls([ + mock.call( + self.record['store_id'], + 'carepoint.stock.warehouse', + ), + ]) diff --git a/connector_carepoint/tests/models/test_stock_warehouse.py b/connector_carepoint/tests/models/test_stock_warehouse.py new file mode 100644 index 0000000..0dbd07a --- /dev/null +++ b/connector_carepoint/tests/models/test_stock_warehouse.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Copyright 2015-2016 LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import mock + +from openerp.addons.connector_carepoint.models import stock_warehouse + +from ..common import SetUpCarepointBase + + +class EndTestException(Exception): + pass + + +class StockWarehouseTestBase(SetUpCarepointBase): + + def setUp(self): + super(StockWarehouseTestBase, self).setUp() + self.model = 'carepoint.stock.warehouse' + self.mock_env = self.get_carepoint_helper( + self.model + ) + self.record = { + 'store_id': 123, + 'name': ' warehouse ', + } + + +class TestStockWarehouseImportMapper(StockWarehouseTestBase): + + def setUp(self): + super(TestStockWarehouseImportMapper, self).setUp() + self.Unit = stock_warehouse.StockWarehouseImportMapper + self.unit = self.Unit(self.mock_env) + + def test_code(self): + expect = {'code': self.record['name'].strip()} + res = self.unit.code(self.record) + self.assertDictEqual(expect, res) + + def test_is_pharmacy(self): + expect = {'is_pharmacy': True} + res = self.unit.is_pharmacy(self.record) + self.assertDictEqual(expect, res) + + def test_carepoint_id(self): + expect = {'carepoint_id': self.record['store_id']} + res = self.unit.carepoint_id(self.record) + self.assertDictEqual(expect, res) + + def test_partner_id_company_id_get_binder(self): + """ It should get binder for pharmacy """ + with mock.patch.object(self.unit, 'binder_for'): + self.unit.binder_for.side_effect = EndTestException + with self.assertRaises(EndTestException): + self.unit.partner_id_company_id(self.record) + self.unit.binder_for.assert_called_once_with( + 'carepoint.medical.pharmacy' + ) + + def test_partner_id_company_id_to_odoo(self): + """ It should get Odoo record for pharmacy """ + with mock.patch.object(self.unit, 'binder_for'): + self.unit.binder_for().to_odoo.side_effect = EndTestException + with self.assertRaises(EndTestException): + self.unit.partner_id_company_id(self.record) + self.unit.binder_for().to_odoo.assert_called_once_with( + self.record['store_id'], browse=True, + ) + + def test_partner_id_company_id_return(self): + """ It should return formatted partner_id_company_id """ + with mock.patch.object(self.unit, 'binder_for'): + res = self.unit.partner_id_company_id(self.record) + expect = self.unit.binder_for().to_odoo() + expect = { + 'company_id': expect.company_id.id, + 'partner_id': expect.partner_id.id, + } + self.assertDictEqual(expect, res) + + def test_route_ids(self): + expect = ['route_ids', 'prescription_route_id', 'otc_route_id'] + res = self.unit.route_ids(self.record) + for key in res.keys(): + self.assertIn(key, expect) diff --git a/connector_carepoint/tests/test_base_exporter.py b/connector_carepoint/tests/test_base_exporter.py index fd19828..9ed6a07 100644 --- a/connector_carepoint/tests/test_base_exporter.py +++ b/connector_carepoint/tests/test_base_exporter.py @@ -44,6 +44,7 @@ def _new_record(self, sync_date=False): return self.env[self.model].create({ 'name': 'Test', 'sync_date': sync_date, + 'warehouse_id': self.env.ref('stock.warehouse0').id, }) def test_exporter_init_binding_id(self): diff --git a/connector_carepoint/tests/test_binder.py b/connector_carepoint/tests/test_binder.py index 34bd2f9..99de95d 100644 --- a/connector_carepoint/tests/test_binder.py +++ b/connector_carepoint/tests/test_binder.py @@ -30,6 +30,7 @@ def _new_record(self, bind=True): 'name': 'Test Pharm', 'carepoint_id': self.carepoint_id if bind else None, 'backend_id': self.backend.id, + 'warehouse_id': self.env.ref('stock.warehouse0').id, }) def test_to_odoo_unwrap(self): diff --git a/connector_carepoint/tests/test_carepoint_backend.py b/connector_carepoint/tests/test_carepoint_backend.py index 36ab783..ae22490 100644 --- a/connector_carepoint/tests/test_carepoint_backend.py +++ b/connector_carepoint/tests/test_carepoint_backend.py @@ -140,13 +140,13 @@ def test_cron_import_sale_order_import(self): self.backend.cron_import_sale_order() mk().import_sale_order.assert_called_once_with() - def test_import_medical_medicament(self): + def test_import_carepoint_item(self): """ It should import proper model on date field """ with mock.patch.object(self.backend, '_import_from_date') as mk: - self.backend.import_medical_medicament() + self.backend.import_carepoint_item() mk.assert_called_once_with( - 'carepoint.medical.medicament', - 'import_medicaments_from_date', + 'carepoint.carepoint.item', + 'import_items_from_date', ) def test_import_medical_patient(self): diff --git a/connector_carepoint/tests/test_carepoint_deleter.py b/connector_carepoint/tests/test_carepoint_deleter.py index c4526ec..c050579 100644 --- a/connector_carepoint/tests/test_carepoint_deleter.py +++ b/connector_carepoint/tests/test_carepoint_deleter.py @@ -38,6 +38,7 @@ def _new_record(self, sync_date=False): return self.env[self.model].create({ 'name': 'Test', 'sync_date': sync_date, + 'warehouse_id': self.env.ref('stock.warehouse0').id, }) def test_run_not_implemented(self): diff --git a/connector_carepoint/tests/test_carepoint_exporter.py b/connector_carepoint/tests/test_carepoint_exporter.py index bd988b3..4210f74 100644 --- a/connector_carepoint/tests/test_carepoint_exporter.py +++ b/connector_carepoint/tests/test_carepoint_exporter.py @@ -76,6 +76,7 @@ def _new_exporter(self, carepoint_id=None, binding_record=None, def _new_record(self): return self.env[self.model].create({ 'name': 'Test', + 'warehouse_id': self.env.ref('stock.warehouse0').id, }) def test_lock_sql(self): diff --git a/connector_carepoint/tests/test_carepoint_importer.py b/connector_carepoint/tests/test_carepoint_importer.py index 4d1a1c3..429d296 100644 --- a/connector_carepoint/tests/test_carepoint_importer.py +++ b/connector_carepoint/tests/test_carepoint_importer.py @@ -62,6 +62,7 @@ def _new_record(self, sync_date='2016-01-01 00:00:00'): return self.env[self.model].create({ 'name': 'Test', 'sync_date': sync_date, + 'warehouse_id': self.env.ref('stock.warehouse0').id, }) def _new_importer(self, carepoint_id=None, carepoint_record=None): diff --git a/connector_carepoint/tests/test_connector.py b/connector_carepoint/tests/test_connector.py index 0176da8..3418f59 100644 --- a/connector_carepoint/tests/test_connector.py +++ b/connector_carepoint/tests/test_connector.py @@ -29,11 +29,11 @@ def _new_record(self): return self.env[self.model].create({ 'name': 'Test Pharm', 'carepoint_id': self.carepoint_id, + 'warehouse_id': self.env.ref('stock.warehouse0').id, }) def test_default_backend_id(self): - res = self._new_record() - self.assertEqual(self.backend, res.backend_id) + self.assertEqual(self.backend, self.binding_id.backend_id) def test_get_environment_gets_backend_record(self): """ It should browse for backend_record for id """ diff --git a/connector_carepoint/tests/test_consumer.py b/connector_carepoint/tests/test_consumer.py index 0de5a59..17f0bc4 100644 --- a/connector_carepoint/tests/test_consumer.py +++ b/connector_carepoint/tests/test_consumer.py @@ -24,6 +24,7 @@ def _new_record(self): 'name': 'Test Pharm', 'carepoint_id': 1234567, 'backend_id': self.backend.id, + 'warehouse_id': self.env.ref('stock.warehouse0').id, }) def test_delay_export_context_no_export(self): diff --git a/connector_carepoint/tests/test_related_action.py b/connector_carepoint/tests/test_related_action.py index 9a384c4..0c0b883 100644 --- a/connector_carepoint/tests/test_related_action.py +++ b/connector_carepoint/tests/test_related_action.py @@ -39,6 +39,7 @@ def _new_record(self): 'name': 'Test Pharm', 'carepoint_id': 1234567, 'backend_id': self.backend.id, + 'warehouse_id': self.env.ref('stock.warehouse0').id, }) def test_unwrap_binding_no_binding(self): diff --git a/connector_carepoint/unit/binder.py b/connector_carepoint/unit/binder.py index 15fea7d..e7b2013 100644 --- a/connector_carepoint/unit/binder.py +++ b/connector_carepoint/unit/binder.py @@ -23,7 +23,7 @@ class CarepointModelBinder(CarepointBinder): """ _model_name = [ 'carepoint.medical.pharmacy', - 'carepoint.medical.medicament', + 'carepoint.carepoint.item', 'carepoint.medical.physician', 'carepoint.medical.patient', 'carepoint.medical.prescription.order', @@ -33,11 +33,13 @@ class CarepointModelBinder(CarepointBinder): 'carepoint.carepoint.address.physician', 'carepoint.carepoint.address.pharmacy', 'carepoint.carepoint.account', + 'carepoint.carepoint.vendor', 'carepoint.account.invoice.line', 'carepoint.sale.order', 'carepoint.sale.order.line', 'carepoint.procurement.order', 'carepoint.stock.picking', + 'carepoint.stock.warehouse', 'carepoint.res.users', 'carepoint.fdb.ndc', 'carepoint.fdb.gcn', diff --git a/connector_carepoint/views/carepoint_backend_view.xml b/connector_carepoint/views/carepoint_backend_view.xml index b7b1709..5d8db53 100644 --- a/connector_carepoint/views/carepoint_backend_view.xml +++ b/connector_carepoint/views/carepoint_backend_view.xml @@ -179,12 +179,12 @@
-
-