Rev 5620 | Rev 9486 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#!/usr/bin/python# coding: ascii'''This script is used to load item details in the catalog database.It's now mostly used for Accessories since they come in huge numbers.@author: Chandranshu'''from elixir import *from shop2020.model.v1.catalog.impl import DataServicefrom shop2020.model.v1.inventory.impl import DataService as IDataServicefrom shop2020.model.v1.catalog.impl.DataService import Item, EntityIDGenerator, \ItemChangeLogfrom shop2020.model.v1.inventory.impl.DataService import Vendor, \VendorItemMapping, VendorItemPricingfrom shop2020.thriftpy.model.v1.catalog.ttypes import status, ItemTypeimport csvimport datetimeimport optparseimport xlrdif __name__ == '__main__' and __package__ is None:import sysimport ossys.path.insert(0, os.getcwd())def load_item_data(filename, vendorId, full_update, dry_run):DataService.initialize('catalog')IDataService.initialize('inventory')vendor = Vendor.get_by(id=vendorId)if vendor is None:raise Exception("No vendor found for the id: " + str(vendorId))workbook = xlrd.open_workbook(filename)sheet = workbook.sheet_by_index(0)num_rows = sheet.nrowsupdatedOn = datetime.datetime.now()new_items = []updated_items = []not_created_items = []for rownum in range(1, num_rows):print sheet.row_values(rownum)our_brand, our_model_number, our_model_name, our_color,\product_group, brand, model_number, model_name, color,\dp, mrp, mop, sp, xfer_price,\comments, weight, start_date, deal_text, deal_value,\warranty_period, serialized, hasItemNo, preferredVendor = sheet.row_values(rownum)[0:23]print product_groupif isinstance(model_number, float):model_number = str(int(model_number))if isinstance(our_model_number, float):our_model_number = str(int(our_model_number))if our_brand == '':our_brand = brandif our_model_number == '':our_model_number = model_numberif our_model_name == '':our_model_name = model_nameif our_color == '':our_color = colorif sp == '':sp = mopitem = Nonesimilar_item = Nonevendor_item_pricing = Nonekey = product_group.strip().lower() + '|' + brand.strip().lower() + '|' + model_number.strip().lower() + '|' + color.strip().lower()# Check if a similar items already exists in our databasesimilar_items = Item.query.filter_by(brand=our_brand.strip(), model_number=our_model_number.strip(), model_name=our_model_name.strip()).all()# Check if a similar item already exists in our databasefor old_item in similar_items:if old_item.color != None and old_item.color.strip().lower() == our_color.strip().lower():item = old_itembreak# Check if a similar item already exists in our database with out valid color if similar item with same color is not foundif item is None:for old_item in similar_items:if not check_color_valid(old_item.color):item = old_itembreaki = 0color_of_similar_item = None# Check if a similar item already exists in our database to be used to get catalog_item_idfor old_item in similar_items:# get a similar item already existing in our database with valid colorif check_color_valid(old_item.color):similar_item = old_itemcolor_of_similar_item = similar_item.colorbreaki = i + 1# get a similar item already existing in our database if similar item with valid color is not foundif i == len(similar_items):similar_item = old_itemcolor_of_similar_item = similar_item.color# Check if a similar item that is obtained above is having a valid colorif check_color_valid(color_of_similar_item):# if a similar item that is obtained above is having a valid color and new item is about to be created with out valid color it is not done.# since for example if their is a item with red color in our database and we are creating a new item with no color for the same product which is wrong.if item is None and not check_color_valid(our_color):not_created_items.append(rownum)continueif item is None:#print "[ADDING:]{0} {1} {2} {3} to our catalogue.".format(brand, model_number, model_name, color)new_items.append(rownum)item = Item()item.brand = our_brand.strip()item.product_group = product_group.strip()item.model_number = our_model_number.strip()item.model_name = our_model_name.strip()item.color = our_color.strip()item.status = status.IN_PROCESSitem.status_description = "This item is in process"item.addedOn = updatedOnvendor_item_mapping = VendorItemMapping(vendor=vendor, item=item, item_key=key)vendor_item_pricing = VendorItemPricing(vendor=vendor, item=item)session.add(item)session.add(vendor_item_mapping)session.add(vendor_item_pricing)if similar_item is None or similar_item.catalog_item_id is None:# If there is no similar item in the database from before,# use the entity_id_generatorentity_id = EntityIDGenerator.query.first()item.catalog_item_id = entity_id.id + 1entity_id.id = entity_id.id + 1if similar_item is not None and similar_item.catalog_item_id is None:similar_item.catalog_item_id = entity_id.idelse:#If a similar item already exists for a product group, brand and model_number, set it as same.item.catalog_item_id = similar_item.catalog_item_iditem.category = similar_item.categoryitem.product_group = similar_item.product_groupitem.status = similar_item.statusitem.status_description = similar_item.status_description#Use the same brand, model name and model number as in similar item in databaseitem.brand = similar_item.branditem.model_name = similar_item.model_nameitem.model_number = similar_item.model_numberelse:# If this item already existed and one of its price parameters has changed# in which case we add it to the list of updated items for reporting.if item.status == status.PHASED_OUT:item.status = status.IN_PROCESS #Not the ideal choice but we don't know whether content has been generated for it beforehand.item.status_description = "This item is in process"if check_color_valid(our_color) and (item.color == None or item.color.strip().lower() != our_color.strip().lower()):item.color = our_color.strip()vendor_item_mapping = VendorItemMapping.get_by(vendor=vendor, item=item)if vendor_item_mapping is None:vendor_item_mapping = VendorItemMapping(vendor=vendor, item=item, item_key=key)session.add(vendor_item_mapping)else:vendor_item_mapping.item_key = keyvendor_item_pricing = VendorItemPricing.get_by(vendor=vendor, item=item)if vendor_item_pricing is None:vendor_item_pricing = VendorItemPricing(vendor=vendor, item=item)session.add(vendor_item_pricing)if item.mrp != mrp or vendor_item_pricing.dealerPrice != dp or vendor_item_pricing.transfer_price != xfer_price or item.sellingPrice != sp:updated_items.append(sheet.row_values(rownum)[0:23] + [item.mrp, vendor_item_pricing.dealerPrice, vendor_item_pricing.transfer_price, item.sellingPrice])if dp != "":item.sellingPrice = dpvendor_item_pricing.dealerPrice = dpif mrp != "" and mop != "" and mrp < mop:raise Exception("[BAD MRP and MOP:] for {0} {1} {2} {3}. MRP={4}. MOP={5}".format(brand, model_number, model_name, color, mrp, mop))if mrp != "" and sp != "" and mrp < sp:raise Exception("[BAD MRP and SP:] for {0} {1} {2} {3}. MRP={4}. SP={5}".format(brand, model_number, model_name, color, mrp, sp))if mop != "" and xfer_price != "" and xfer_price > mop:raise Exception("[BAD MOP and TP:] for {0} {1} {2} {3}. TP={4}. MOP={5}".format(brand, model_number, model_name, color, xfer_price, mop))if preferredVendor == None or preferredVendor == "":raise Exception("[Preferred Vendor required:] for {0} {1} {2} {3}".format(brand, model_number, model_name, color))else:try:item.preferredVendor = int(preferredVendor)except:raise Exception("[Preferred Vendor should be number:] for {0} {1} {2} {3}. preferredVendor={4}".format(brand, model_number, model_name, color, preferredVendor))if serialized == None or serialized == "":raise Exception("[Serialized required:] for {0} {1} {2} {3}".format(brand, model_number, model_name, color))else:try:if serialized:item.type = ItemType.SERIALIZEDelse:item.type = ItemType.NON_SERIALIZEDexcept:raise Exception("[Serialized should be either TRUE(SERIALIZED) or FALSE(NON_SERIALIZED):] for {0} {1} {2} {3}. serialized={4}".format(brand, model_number, model_name, color, serialized))if hasItemNo == None or hasItemNo == "":raise Exception("[hasItemNo required:] for {0} {1} {2} {3}".format(brand, model_number, model_name, color))else:try:if hasItemNo:item.hasItemNo = 1else:item.hasItemNo = 0except:raise Exception("[hasItemNo should be either TRUE or FALSE:] for {0} {1} {2} {3}. hasItemNo={4}".format(brand, model_number, model_name, color, hasItemNo))if warranty_period != "":try:item.warranty_period = int(warranty_period)except:passif mrp != "":item.mrp = mrpif mop != "":vendor_item_pricing.mop = mopif xfer_price !="":vendor_item_pricing.transfer_price = xfer_priceif start_date is not None and start_date != '':#If a start date has been specified, it takes precedence.item.startDate = datetime.datetime(*xlrd.xldate_as_tuple(start_date, workbook.datemode))elif item.startDate == None or item.startDate == '':#If start date is not specified and item's start date is not set, set it to current timeitem.startDate = datetime.datetime.now()item.sellingPrice = spif weight != "":item.weight = weightitem.updatedOn = updatedOnitem_change_log = ItemChangeLog()item_change_log.new_status = item.statusitem_change_log.timestamp = updatedOnitem_change_log.item = itemif not dry_run:session.commit()write_report("/tmp/items_not_created_dueto_color.csv", not_created_items, sheet, False)write_report("/tmp/new_items.csv", new_items, sheet, False)write_report("/tmp/updated_items.csv", updated_items, sheet, True)if (not dry_run) and full_update:query_string = "UPDATE " + str(Item.table) + " SET status=" + str(status.PHASED_OUT) + ", status_description='This item has been phased out'" + ", updatedOn='"+ str(updatedOn) +"'"+\" WHERE updatedOn <> '" + str(updatedOn) + "'";session.execute(query_string, mapper=Item)session.commit()print "Successfully updated the item list information."def check_color_valid(color):if color is not None:color = color.strip().lower()if color != '' and color != 'na' and color != 'blank' and color != '(blank)':return Truereturn Falsedef write_report(filename, items, sheet, is_item):'''Iterates through the items list and writes all the values to the specifiedfilename in the CSV format. 'is_item' indicates whether the list consistsof row numbers or complete row data.'''items_writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_ALL)items_writer.writerow(sheet.row_values(0)[0:23] + ['Old MRP', 'Old DP', 'Old TP', 'Old SP'])if is_item:#The list contains the complete rows.for item in items:print itemitems_writer.writerow([str(value) for value in item])else:#The list only has row numbers. We've to fetch the data ourselves.for i in items:print sheet.row_values(i)items_writer.writerow([str(value) for value in sheet.row_values(i)[0:23]])def main():parser = optparse.OptionParser()parser.add_option("-f", "--file", dest="filename",default="ItemList.xls", type="string",help="Read the item list from FILE",metavar="FILE")parser.add_option("-v", "--vendor", dest="vendor",type="int",help="Update the pricing information for VENDOR",metavar="VENDOR")parser.add_option("-d", "--dry-run", dest="dry_run",action="store_true",help="Dry run only reporting on pending changes.Please note that some of the items can be reported twice.")parser.add_option("-a", "--full", dest="full_update",action="store_true",help="In a full update, all older items are marked as PHASED_OUT. Also see -pm.")parser.add_option("-p", "--partial", dest="full_update",action="store_false",help="In a partial update, older items are left as is. Also see -fm.")parser.set_defaults(full_update=False, dry_run=False, vendor=1)(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?")filename = options.filenameload_item_data(filename, options.vendor, options.full_update, options.dry_run)if __name__ == '__main__':main()