# -*- coding: utf-8; -*- ################################################################################ # # Rattail -- Retail Software Framework # Copyright © 2010-2020 Lance Edgar # # This file is part of Rattail. # # Rattail is free software: you can redistribute it and/or modify it under the # terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # Rattail is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # Rattail. If not, see . # ################################################################################ """ DataSync for CORE POS """ from corepos.db.office_op import Session as CoreSession, model as corepos from rattail.db import model from rattail.datasync import DataSyncWatcher, NewDataSyncImportConsumer class CoreOfficeOpWatcher(DataSyncWatcher): """ DataSync watcher for the CORE ``office_op`` database. """ prunes_changes = True def get_changes(self, lastrun): session = CoreSession() changes = session.query(corepos.Change).all() session.expunge_all() session.close() if changes: return [ (c.id, model.DataSyncChange( payload_type=c.object_type, payload_key=c.object_key, deletion=c.deleted)) for c in changes] def prune_changes(self, keys): deleted = 0 session = CoreSession() for key in keys: change = session.query(corepos.Change).get(key) if change: session.delete(change) session.flush() deleted += 1 session.commit() session.close() return deleted class COREPOSProductWatcher(DataSyncWatcher): """ DataSync watcher for the CORE POS database. """ def get_changes(self, lastrun): if not lastrun: return changes = [] session = CoreSession() lastrun = self.localize_lastrun(session, lastrun) # Department departments = session.query(corepos.Department)\ .filter(corepos.Department.modified >= lastrun)\ .all() if departments: changes.extend([ (None, model.DataSyncChange( payload_type='Department', payload_key=str(dept.number))) for dept in departments]) # TODO: subdepartment table doesn't have a modified flag? # # Subdepartment # subdepartments = session.query(corepos.Subdepartment)\ # .filter(corepos.Subdepartment.modified >= lastrun)\ # .all() # if subdepartments: # changes.extend([ # (None, # model.DataSyncChange( # payload_type='Subdepartment', # payload_key=six.text_type(subdept.subdept_no))) # for subdept in subdepartments]) # TODO: vendor table doesn't have a modified flag? # # Vendor # vendors = session.query(corepos.Vendor)\ # .filter(corepos.Vendor.modified >= lastrun)\ # .all() # if vendors: # changes.extend([ # (None, # model.DataSyncChange( # payload_type='Vendor', # payload_key=six.text_type(vendor.vendorID))) # for vendor in vendors]) # Product products = session.query(corepos.Product)\ .filter(corepos.Product.modified >= lastrun)\ .all() if products: changes.extend([ (None, model.DataSyncChange( payload_type='Product', payload_key=product.upc)) for product in products if product.upc]) session.close() return changes class FromRattailToCore(NewDataSyncImportConsumer): """ Rattail -> CORE POS datasync consumer """ handler_spec = 'rattail_corepos.corepos.importing.rattail:FromRattailToCore' def begin_transaction(self): self.corepos_session = CoreSession() def rollback_transaction(self): self.corepos_session.rollback() self.corepos_session.close() def commit_transaction(self): self.corepos_session.commit() self.corepos_session.close() def process_changes(self, session, changes): """ Process all the given changes, coming from Rattail. """ # TODO: this probably doesn't accomplish anything here? if self.runas_username: session.set_continuum_user(self.runas_username) # update all importers with current Rattail/CORE sessions for importer in self.importers.values(): importer.host_session = session importer.session = self.corepos_session # also establish the API client for each! importer.establish_api() # next pass syncs all Vendor changes types = [ 'Vendor', 'VendorPhoneNumber', 'VendorEmailAddress', ] for change in [c for c in changes if c.payload_type in types]: vendor = self.get_host_vendor(session, change) if vendor: # TODO: what about "deletions" - not sure what happens yet self.process_change(session, self.importers['Vendor'], host_object=vendor) # self.process_change(session, self.importers['VendorContact'], # host_object=vendor) def get_host_vendor(self, session, change): if change.payload_type == 'Vendor': return session.query(model.Vendor).get(change.payload_key) if change.payload_type == 'VendorPhoneNumber': phone = session.query(model.VendorPhoneNumber).get(change.payload_key) if phone: return phone.vendor if change.payload_type == 'VendorEmailAddress': email = session.query(model.VendorEmailAddress).get(change.payload_key) if email: return email.vendor