from datetime import datetime from decimal import Decimal from optparse import OptionParser from os import path from settings import get_settings from pos_connection import PosConnection from categories import get_category_mapping from magento_api import MagentoAPI, flatten_category_tree from gui import run_gui class Logger(object): def __init__(self, settings): self.file = open(settings.get('log', 'file_name'), 'a') def created_category(self, category): self.file.write('%(time)s - Created Category #%(id)i: %(name)s, Level %(level)i\n' % { 'time': datetime.now(), 'id': category.id, 'name': category.name, 'level': category.get_level(), }) def sync_products(self, skus): self.file.write('%(time)s - Sync Products: %(sku)s\n' % { 'time': datetime.now(), 'sku': ', '.join(skus), }) def set_inventory(self, sku, qty): self.file.write('%(time)s - Set Inventory %(sku)s: %(qty)s\n' % { 'time': datetime.now(), 'sku': sku, 'qty': qty, }) def progress(self, string): print string class Sync(object): def __init__(self, settings): self.settings = settings self.logger = Logger(settings) self.pos_connection = PosConnection(settings) self.magento_api = MagentoAPI(settings) self.category_mapping = get_category_mapping(self.settings) def sync_categories(self): magento_categories = flatten_category_tree(self.magento_api.get_category_tree()) categories_to_sync = [] def sync_category(category): if category.name in magento_categories: category.id = magento_categories[category.name] else: categories_to_sync.append(category) for child in category.children: sync_category(child) sync_category(self.category_mapping.root) self.logger.progress("Syncing %i categories" % len(categories_to_sync)) for category in categories_to_sync: category.id = int(self.magento_api.create_category(category.parent.id, category.name)) self.logger.created_category(category) def sync_products(self): magento_products = self.magento_api.get_product_list() magento_skus = set(x['sku'] for x in magento_products) products_to_sync = [] for item in self.pos_connection.get_items(): if item['item_no'] in magento_skus: continue if item['category'] in self.category_mapping.pos_categories: item['category_ids'] = [self.category_mapping.pos_categories[item['category']].id] products_to_sync.append(item) self.logger.progress("Syncing %i products" % len(products_to_sync)) if products_to_sync: self.magento_api.create_products(products_to_sync) def sync_inventory(self): self.pos_connection.force_inventory_table() pos_quantities = list(self.pos_connection.get_item_quantities()) skus = [x['item_no'] for x in pos_quantities] magento_quantities = self.magento_api.get_quantities(skus) self.logger.progress("Syncing %i inventories" % len(pos_quantities)) total = len(pos_quantities) current = 0.0 last_percent = 0.00 for quantity in pos_quantities: sku = quantity['item_no'] last_qty = quantity['sync_quantity'] pos_qty = quantity['quantity_on_hand'] if last_qty is None: self.magento_api.update_quantity(sku, pos_qty) self.pos_connection.add_sync_quantity(sku, pos_qty) self.logger.set_inventory(sku, pos_qty) else: magento_qty = Decimal(magento_quantities[sku]) new_qty = last_qty + (pos_qty - last_qty) + (magento_qty - last_qty) if new_qty != magento_qty: self.magento_api.update_quantity(sku, new_qty) if new_qty != pos_qty: self.pos_connection.set_item_quantity(sku, new_qty) if new_qty != last_qty: self.pos_connection.set_sync_quantity(sku, new_qty) self.logger.set_inventory(sku, new_qty) current_percent = round(current / total, 2) * 100 if last_percent < current_percent : self.logger.progress('Syncing Inventory: %.2f%%' % current_percent) last_percent = current_percent current += 1.0 def __call__(self): self.sync_categories() self.sync_products() self.sync_inventory() self.logger.progress("Finished!") def main(): dir_name = path.dirname(__file__) if dir_name: cfg_file = "%s/sync.cfg" % dir_name else: cfg_file = "sync.cfg" parser = OptionParser() parser.add_option( "-g", "--gui", dest = "use_gui", default = True, help = "Use GUI (Default: True)", ) parser.add_option( "-c", "--config", dest = "cfg_file", default = cfg_file, help = "Configuration file (required)", ) options, _ = parser.parse_args() if options.cfg_file: settings = get_settings(options.cfg_file) sync = Sync(settings) if options.use_gui: run_gui(sync) else: sync() else: parser.print_help() if __name__ == '__main__': main() # the output: """ Syncing 0 categories Loading Magento products Loading Magento Products: 3.39% Loading Magento Products: 6.79% Loading Magento Products: 10.18% Loading Magento Products: 13.58% Loading Magento Products: 16.97% Loading Magento Products: 20.37% Loading Magento Products: 23.76% Loading Magento Products: 27.16% Loading Magento Products: 30.55% Loading Magento Products: 33.94% Loading Magento Products: 37.34% Loading Magento Products: 40.73% Loading Magento Products: 44.13% Loading Magento Products: 47.52% Loading Magento Products: 50.92% Loading Magento Products: 54.31% Loading Magento Products: 57.71% Loading Magento Products: 61.10% Loading Magento Products: 64.49% Loading Magento Products: 67.89% Loading Magento Products: 71.28% Loading Magento Products: 74.68% Loading Magento Products: 78.07% Loading Magento Products: 81.47% Loading Magento Products: 84.86% Loading Magento Products: 88.26% Loading Magento Products: 91.65% Loading Magento Products: 95.04% Loading Magento Products: 98.44% Loading Magento Products: 100.00% Loading POS products 'NoneType' object is not iterable eef1000 description None 'NoneType' object is not iterable bnjb description None 'NoneType' object is not iterable hadm11 name None 'NoneType' object is not iterable hadm11 short_description None 'NoneType' object is not iterable hadm11 description None 'NoneType' object is not iterable mbr60o1 description None 'NoneType' object is not iterable layan1 description None 'NoneType' object is not iterable mbr60o10 description None 'NoneType' object is not iterable mbr60o description None 'NoneType' object is not iterable eb20 description None 'NoneType' object is not iterable ethermbf description None 'NoneType' object is not iterable ebbh description None 'NoneType' object is not iterable bipa description None 'NoneType' object is not iterable mbr120o1 description None 'NoneType' object is not iterable efb12d description None 'NoneType' object is not iterable mbr120o description None Updating Products: 5.32% Updating Products: 10.64% Updating Products: 15.96% Updating Products: 21.28% Updating Products: 26.60% Updating Products: 31.91% Updating Products: 37.23% Updating Products: 42.55% Updating Products: 47.87% Updating Products: 53.19% Updating Products: 58.51% Updating Products: 63.83% Updating Products: 69.15% Updating Products: 74.47% Updating Products: 79.79% Updating Products: 85.11% Updating Products: 90.43% Updating Products: 95.74% Updating Products: 100.00% Loading Magento Images: 3.39% Loading Magento Images: 6.79% Loading Magento Images: 10.18% Loading Magento Images: 13.58% Loading Magento Images: 16.97% Loading Magento Images: 20.37% Loading Magento Images: 23.76% Loading Magento Images: 27.16% Loading Magento Images: 30.55% Loading Magento Images: 33.94% Loading Magento Images: 37.34% Loading Magento Images: 40.73% Loading Magento Images: 44.13% Loading Magento Images: 47.52% Loading Magento Images: 50.92% Loading Magento Images: 54.31% Loading Magento Images: 57.71% Loading Magento Images: 61.10% Loading Magento Images: 64.49% Loading Magento Images: 67.89% Loading Magento Images: 71.28% Loading Magento Images: 74.68% Loading Magento Images: 78.07% Loading Magento Images: 81.47% Loading Magento Images: 84.86% Loading Magento Images: 88.26% Loading Magento Images: 91.65% Loading Magento Images: 95.04% Loading Magento Images: 98.44% Loading Magento Images: 100.00% Exception in Tkinter callback Traceback (most recent call last): File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1410, in __call__ return self.func(*args) File "./sync.py", line 207, in __call__ self.sync_products() File "./sync.py", line 103, in sync_products self._update_images(pos_products, product_images) File "./sync.py", line 194, in _update_images 'magento': [x['file'] for x in magento_products[sku]], TypeError: string indices must be integers, not str """