Blame | Last modification | View Log | RSS feed
#!/usr/bin/python'''This script is used to match our inventory report with that of avendor. Run the script with -h option to learn more.@author: Chandranshu'''import optparseimport sysimport csvimport xlrd#if __name__ == '__main__' and __package__ is None:# import os# sys.path.insert(0, os.getcwd())def read_vendor_item_mapping(filename):'''Returns a dictionary containing the item id corresponding to the vendor key of a product.This is used to read the inventory data we get from the warehouse.'''reader = csv.reader(open(filename, "rb"), dialect=csv.excel_tab)vendor_item_mapping = {}try:for row in reader:if reader.line_num == 1:continuekey = row[0].strip()val = int(row[1])vendor_item_mapping[key]=valexcept csv.Error, e:sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))return vendor_item_mappingdef read_inventory_data(filename, vendor_mapping_filename, working_product_group):'''Returns a dictionary containing the availability of items in warehosue keyed bythe id of the item in our catalog.Parameters:- filename: The XLS file to read the warehouse inventory from.- vendor_mapping_filename: The CSV file to read the item mapping from.- working_product_group: The product group to use overriding the one specified in the inventory report.'''vendor_item_mapping = read_vendor_item_mapping(vendor_mapping_filename);workbook = xlrd.open_workbook(filename)sheet = workbook.sheet_by_index(0)num_rows = sheet.nrowsavailability = {}for rownum in range(1, num_rows):unused_company, unused_division, unused_store_name, unused_store_code, unused_product_catalog, product_group, brand, model_number, color, unused_item_number, quantity = sheet.row_values(rownum)[0:11]if isinstance(model_number, float):model_number = str(int(model_number))itemid = product_group.strip() + "|" + brand.strip() + "|" + model_number.strip() + "|" + color.strip()itemid = itemid.lower()key = str(itemid)if vendor_item_mapping.has_key(itemid):key = vendor_item_mapping[itemid]if availability.has_key(key):quantity = quantity + availability.get(key)availability[key] = quantityreturn availabilitydef read_local_inventory(filename):'''Returns the following objects:1. A dictionary keying the availability of items in our catalog bythe id of the item in our catalog.2. A list of items whose inventory is zero.3. A dictionary mapping the item id to the availability in our catalog.Parameters:- filename : File to read the local inventory data from'''reader = csv.reader(open(filename, "rb"))availability = {}zero_inventory_items = [['Id', 'Product Group', 'Brand', 'Model', 'Color']]items = {}try:for row in reader:if reader.line_num == 1:continuekey = int(row[0])val = int(row[5])availability[key]=valitems[key] = [row[1], row[2], row[3], row[4]]if val == 0:zero_inventory_items.append([row[0], row[1], row[2], row[3], row[4]])except csv.Error, e:sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))return availability, zero_inventory_items, itemsdef write_report(filename, item_list):'''Writes the elements of the given list in the specified file. It uses thedefault CSV writer and hence will fail if the elements of the list useUnicode characters.Parameters:- filename: File to write report to. Existing file, if any, is truncated.- item_list: List whose elements have to be written.'''print "Writing report to: " + filenamewriter = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_MINIMAL)for item in item_list:writer.writerow(item)def compare_stocks(inventory_file, closing_stock_file, vendor_mapping_file, date_string, product_group):'''Does not return anything. Creates three reports by matching the data inthe two given reports:1. Mismatch Report: Lists the differences in stock situation between ourinventory and warehouse.2. Missing Report: Lists the items which are present in the warehouse reportbut absent in our catalog.3. Zero Inventory Report: Lists the items for which we have no inventory.Parameters:- inventory_file: The file containing our inventory details. The fileshould be in CSV format. It should have 5 columns for ProductGroup, Brand, Model, Color and availability.- closing_stock_file: The file containing the inventory situation inone of the warehouses.- date_string: The date these reports are for. Is used to create reports.'''closing_stock = read_inventory_data(closing_stock_file, vendor_mapping_file, product_group)our_inventory, zero_inventory_items, items = read_local_inventory(inventory_file)print closing_stockprint our_inventoryitems_with_inventory_mismatch = [['Id', 'Product Group', 'Brand', 'Model', 'Color', 'Online Retail Stock', 'Hotspot Stock']]items_missing_in_catalog = [['Product Group', 'Brand', 'Model', 'Color']]for key,value in closing_stock.iteritems():if our_inventory.has_key(key):if our_inventory[key]!= value:mismatch_list=[key] + items[key]mismatch_list.append(our_inventory[key])mismatch_list.append(int(value))items_with_inventory_mismatch.append(mismatch_list)else:items_missing_in_catalog.append(str(key).split('|'))write_report("mismatch-" + date_string + ".csv", items_with_inventory_mismatch)write_report("missing-" + date_string + ".csv", items_missing_in_catalog)write_report("zero-inventory-" + date_string + ".csv", zero_inventory_items)def main():parser = optparse.OptionParser()parser.add_option("-i", "--inventory", dest="inventory_file",default="inventory-report.csv", type="string",help="Read the item inventory from INVENTORY_FILE",metavar="INVENTORY_FILE")parser.add_option("-c", "--closingstock", dest="closing_stock_file",default="closing_stock.xls", type="string",help="Read the closing stock from CLOSING_STOCK_FILE",metavar="CLOSING_STOCK_FILE")parser.add_option("-v", "--vendor-mapping", dest="vendor_mapping_file",default="vendor_mapping_1.csv", type="string",help="Read the vendor item mapping from VENDOR_MAPPING_FILE",metavar="VENDOR_MAPPING_FILE")parser.add_option("-d", "--date", dest="date_string",default="xxxxxxxx", type="string",help="Append DATE string to the names of the generated files",metavar="DATE")parser.add_option("-p", "--product-group", dest="product_group",default=None, type="string",help="Assume PRODUCT_GROUP to be the product group of all items",metavar="PRODUCT_GROUP")(options, args) = parser.parse_args()if len(args) != 0:parser.error("You've supplied extra arguments. Are you sure you want to run this program?")compare_stocks(options.inventory_file, options.closing_stock_file, options.vendor_mapping_file, options.date_string, options.product_group)if __name__ == '__main__':main()