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
"""