Subversion Repositories SmartDukaan

Rev

Rev 4717 | Rev 4739 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
626 chandransh 1
#!/usr/bin/python
4090 chandransh 2
'''
3
This script is used to load item details in the catalog database.
4
It's now mostly used for Accessories since they come in huge numbers.
1080 chandransh 5
 
4090 chandransh 6
@author: Chandranshu
7
'''
626 chandransh 8
import optparse
1080 chandransh 9
import csv
626 chandransh 10
import xlrd
11
import datetime
12
 
13
if __name__ == '__main__' and __package__ is None:
14
    import sys
15
    import os
16
    sys.path.insert(0, os.getcwd())
17
 
18
from shop2020.thriftpy.model.v1.catalog.ttypes import status
19
from shop2020.model.v1.catalog.impl import DataService
724 chandransh 20
from shop2020.model.v1.catalog.impl.DataService import Item, EntityIDGenerator,\
1356 chandransh 21
    ItemChangeLog, Vendor, VendorItemPricing, VendorItemMapping
626 chandransh 22
from elixir import *
23
 
1810 chandransh 24
def load_item_data(filename, vendorId, category, full_update, dry_run, supplied_product_group):
1250 chandransh 25
    DataService.initialize('catalog')
1356 chandransh 26
 
27
    vendor = Vendor.get_by(id=vendorId)
28
    if vendor is None:
29
        raise Exception("No vendor found for the id: " + str(vendorId))
626 chandransh 30
 
31
    workbook = xlrd.open_workbook(filename)
32
    sheet = workbook.sheet_by_index(0)
33
    num_rows = sheet.nrows
34
    updatedOn = datetime.datetime.now()
1080 chandransh 35
    new_items = []
1264 chandransh 36
    updated_items = []
4717 phani.kuma 37
    not_created_items = []
1356 chandransh 38
 
39
    existing_vendor_item_mappings = VendorItemMapping.query.filter_by(vendor=vendor, vendor_category=category).all()
40
    existing_vendor_item_mappings_set = set([mapping.item_key for mapping in existing_vendor_item_mappings])
41
 
626 chandransh 42
    for rownum in range(1, num_rows):
1833 chandransh 43
        print sheet.row_values(rownum)
1264 chandransh 44
 
1833 chandransh 45
        if supplied_product_group != None and supplied_product_group != '':
1810 chandransh 46
            our_brand, our_model_number, our_color,\
47
            brand, model_number, model_name, color,\
48
            dp, mrp, mop, sp,\
4717 phani.kuma 49
            comments, hotspot_category, unused_feature, xfer_price, weight, start_date, deal_text, deal_value,\
50
            warranty_period, defaultWarehouse, preferredVendor = sheet.row_values(rownum)[0:22]
1810 chandransh 51
            product_group = supplied_product_group
52
        else:
53
            our_brand, our_model_number, our_color,\
54
            product_group, brand, model_number, model_name, color,\
55
            dp, mrp, mop, sp,\
4717 phani.kuma 56
            comments, hotspot_category, unused_feature, xfer_price, weight, start_date, deal_text, deal_value,\
57
            warranty_period, defaultWarehouse, preferredVendor = sheet.row_values(rownum)[0:23]
1810 chandransh 58
 
1833 chandransh 59
        print product_group
60
 
626 chandransh 61
        if isinstance(model_number, float):
62
            model_number = str(int(model_number))
1810 chandransh 63
 
64
        if our_brand == '':
65
            our_brand = brand
66
        if our_model_number == '':
67
            our_model_number = model_number
68
        if our_color == '':
69
            our_color = color
70
 
1633 chandransh 71
        if sp == '':
72
            sp = mop 
1356 chandransh 73
        item = None
4725 phani.kuma 74
        similar_item = None
1356 chandransh 75
        vendor_item_pricing = None
1080 chandransh 76
 
1356 chandransh 77
        key = product_group.strip().lower() + '|' + brand.strip().lower() + '|' + model_number.strip().lower() + '|' + color.strip().lower()
78
        if key in existing_vendor_item_mappings_set:
79
            existing_vendor_item_mappings_set.remove(key)
80
 
4717 phani.kuma 81
        # Check if a similar items already exists in our database
82
        similar_items = Item.query.filter_by(brand=our_brand.strip(), model_number=our_model_number.strip(), model_name=model_name.strip()).all()
83
 
4725 phani.kuma 84
        # Check if a similar item already exists in our database
4717 phani.kuma 85
        for old_item in similar_items:
4725 phani.kuma 86
            if old_item.color != None and old_item.color.strip().lower() == our_color.strip().lower():
4717 phani.kuma 87
                item = old_item
88
                break
89
 
4725 phani.kuma 90
        # Check if a similar item already exists in our database with out valid color if similar item with same color is not found
626 chandransh 91
        if item is None:
4717 phani.kuma 92
            for old_item in similar_items:
4725 phani.kuma 93
                if not check_color_valid(old_item.color):
4717 phani.kuma 94
                    item = old_item
95
                    break
96
 
97
        i = 0
98
        color_of_similar_item = None
4725 phani.kuma 99
        # Check if a similar item already exists in our database to be used to get catalog_item_id
4717 phani.kuma 100
        for old_item in similar_items:
4725 phani.kuma 101
            # get a similar item already existing in our database with valid color
102
            if check_color_valid(old_item.color):
4717 phani.kuma 103
                similar_item = old_item
104
                color_of_similar_item = similar_item.color
105
                break
106
            i = i + 1
4725 phani.kuma 107
            # get a similar item already existing in our database if similar item with valid color is not found
4717 phani.kuma 108
            if i == len(similar_items):
109
                similar_item = old_item
110
                color_of_similar_item = similar_item.color
4725 phani.kuma 111
 
112
        # Check if a similar item that is obtained above is having a valid color
113
        if check_color_valid(color_of_similar_item):
114
            # 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.
115
            # 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.
116
            if item is None and not check_color_valid(our_color):
4717 phani.kuma 117
                not_created_items.append(rownum)
118
                continue
119
 
120
 
121
        if item is None:
122
            #print "[ADDING:]{0} {1} {2} {3} to our catalogue.".format(brand, model_number, model_name, color)
1080 chandransh 123
            new_items.append(rownum)
626 chandransh 124
            item = Item()
4717 phani.kuma 125
            item.product_group = product_group.strip()
126
            item.brand = our_brand.strip()
127
            item.model_number = our_model_number.strip()
128
            item.model_name = model_name.strip()
129
            item.color = our_color.strip()
626 chandransh 130
            item.status = status.IN_PROCESS
2035 rajveer 131
            item.status_description = "This item is in process"
626 chandransh 132
            item.addedOn = updatedOn
1089 chandransh 133
            item.hotspotCategory = category
1356 chandransh 134
 
1506 chandransh 135
            if category == 'Handsets':
136
                item.preferredWarehouse = 1
137
            else:
138
                item.preferredWarehouse = 2
139
 
1356 chandransh 140
            vendor_item_mapping = VendorItemMapping(vendor=vendor, item=item, item_key=key, vendor_category=category)
1359 chandransh 141
            vendor_item_pricing = VendorItemPricing(vendor=vendor, item=item)
142
 
626 chandransh 143
            session.add(item)
1356 chandransh 144
            session.add(vendor_item_mapping)
1359 chandransh 145
            session.add(vendor_item_pricing)
1080 chandransh 146
 
4717 phani.kuma 147
            if similar_item is None or similar_item.catalog_item_id is None:
148
                # If there is no similar item in the database from before,
149
                # use the entity_id_generator
150
                entity_id = EntityIDGenerator.query.first()
151
                item.catalog_item_id = entity_id.id + 1
152
                entity_id.id = entity_id.id  + 1
153
                if similar_item is not None and similar_item.catalog_item_id is None:
154
                    similar_item.catalog_item_id = entity_id.id
1080 chandransh 155
            else:
4717 phani.kuma 156
                #If a similar item already exists for a product group, brand and model_number, set it as same.
157
                item.catalog_item_id = similar_item.catalog_item_id
158
                item.category = similar_item.category
159
                item.status = similar_item.status
160
                item.status_description = similar_item.status_description
161
                #Use the same brand, model name and model number as in similar item in database
162
                item.brand = similar_item.brand
163
                item.model_name = similar_item.model_name
164
                item.model_number = similar_item.model_number
626 chandransh 165
        else:
1356 chandransh 166
            # If this item already existed and one of its price parameters has changed
1278 chandransh 167
            # in which case we add it to the list of updated items for reporting.
1965 chandransh 168
            if item.status == status.PHASED_OUT:
169
                item.status = status.IN_PROCESS #Not the ideal choice but we don't know whether content has been generated for it beforehand.
2035 rajveer 170
                item.status_description = "This item is in process"
4717 phani.kuma 171
 
4725 phani.kuma 172
            if check_color_valid(our_color) and (item.color == None or item.color.strip().lower() != our_color.strip().lower()):
4717 phani.kuma 173
                item.color = our_color.strip()
174
 
175
            vendor_item_mapping = VendorItemMapping.get_by(vendor=vendor, item=item)
176
            if vendor_item_mapping is None:
177
                vendor_item_mapping = VendorItemMapping(vendor=vendor, item=item, item_key=key, vendor_category=category)
178
                session.add(vendor_item_mapping)
4725 phani.kuma 179
            else:
180
                vendor_item_mapping.item_key = key
181
                vendor_item_mapping.vendor_category = category
182
 
1356 chandransh 183
            vendor_item_pricing = VendorItemPricing.get_by(vendor=vendor, item=item)
184
            if vendor_item_pricing is None:
185
                vendor_item_pricing = VendorItemPricing(vendor=vendor, item=item)
186
                session.add(vendor_item_pricing)
187
 
1633 chandransh 188
            if item.mrp != mrp or vendor_item_pricing.dealerPrice != dp or vendor_item_pricing.transfer_price != xfer_price or item.sellingPrice != sp:
189
                updated_items.append(sheet.row_values(rownum)[0:19] + [item.mrp, item.dealerPrice, item.transfer_price])
2330 rajveer 190
 
1080 chandransh 191
        if dp != "":
192
            item.dealerPrice = dp
193
            item.sellingPrice = dp
1356 chandransh 194
            vendor_item_pricing.dealerPrice = dp
629 rajveer 195
 
1080 chandransh 196
        if mrp != "" and mop != "" and mrp <  mop:
4717 phani.kuma 197
            raise Exception("[BAD MRP and MOP:] for {0} {1} {2} {3}. MRP={4}. MOP={5}".format(brand, model_number, model_name, color, mrp, mop))
1080 chandransh 198
 
1633 chandransh 199
        if mrp != "" and sp != "" and mrp < sp:
4717 phani.kuma 200
            raise Exception("[BAD MRP and SP:] for {0} {1} {2} {3}. MRP={4}. SP={5}".format(brand, model_number, model_name, color, mrp, sp))
1633 chandransh 201
 
1080 chandransh 202
        if mop != "" and xfer_price != "" and xfer_price > mop:
4717 phani.kuma 203
            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))
1320 chandransh 204
#        if mrp != "":
205
#            if item.mrp == None or item.mrp >= mrp:
206
#                item.mrp = mrp
207
#            else:
4717 phani.kuma 208
#                raise Exception("[NEW MRP MORE THAN old MRP:] for {0} {1} {2} {3}. Old mrp={4}. New MRP={5}".format(brand, model_number, model_name, color, item.mrp, mrp))
873 rajveer 209
 
4717 phani.kuma 210
        if defaultWarehouse == None or defaultWarehouse == "":
211
            raise Exception("[Default Warehouse required:] for {0} {1} {2} {3}".format(brand, model_number, model_name, color))
212
        else:
213
            try:
214
                item.defaultWarehouse = int(defaultWarehouse)
215
            except:
216
                raise Exception("[Default Warehouse should be number:] for {0} {1} {2} {3}. defaultWarehouse={4}".format(brand, model_number, model_name, color, defaultWarehouse))
217
 
218
        if preferredVendor == None or preferredVendor == "":
219
            raise Exception("[Preferred Vendor required:] for {0} {1} {2} {3}".format(brand, model_number, model_name, color))
220
        else:
221
            try:
222
                item.preferredVendor = int(preferredVendor)
223
            except:
224
                raise Exception("[Preferred Vendor should be number:] for {0} {1} {2} {3}. preferredVendor={4}".format(brand, model_number, model_name, color, preferredVendor))
225
 
226
        if warranty_period != "":
227
            try:
228
                item.warranty_period = int(warranty_period)
229
            except:
230
                pass               
231
 
1431 chandransh 232
        if mrp != "":
233
            item.mrp = mrp
234
 
629 rajveer 235
        if mop != "":
236
            item.mop = mop
1356 chandransh 237
            vendor_item_pricing.mop = mop
1080 chandransh 238
 
724 chandransh 239
        if xfer_price !="":
240
            item.transfer_price = xfer_price
1356 chandransh 241
            vendor_item_pricing.transfer_price = xfer_price
1080 chandransh 242
 
2088 chandransh 243
        if start_date is not None and start_date != '':
244
            #If a start date has been specified, it takes precedence.
245
            item.startDate = datetime.datetime(*xlrd.xldate_as_tuple(start_date, workbook.datemode))
246
        elif item.startDate == None or item.startDate == '': 
247
            #If start date is not specified and item's start date is not set, set it to current time
1431 chandransh 248
            item.startDate = datetime.datetime.now()
1080 chandransh 249
 
1633 chandransh 250
        item.sellingPrice = sp
1080 chandransh 251
 
629 rajveer 252
        if weight != "":    
253
            item.weight = weight
1080 chandransh 254
 
255
#        item.bestDealText = deal_text
256
#        if deal_value != "":
257
#            item.bestDealValue = deal_value
258
#        item.comments = comments
259
 
626 chandransh 260
        item.updatedOn = updatedOn
724 chandransh 261
 
262
        item_change_log = ItemChangeLog()
263
        item_change_log.new_status = item.status
264
        item_change_log.timestamp = updatedOn
265
        item_change_log.item = item
1080 chandransh 266
 
267
        if not dry_run:
268
            session.commit()
269
 
4717 phani.kuma 270
    write_report("items_not_created_dueto_color.csv", not_created_items, sheet, False)
1264 chandransh 271
    write_report("new_items.csv", new_items, sheet, False)
272
    write_report("updated_items.csv", updated_items, sheet, True)
1356 chandransh 273
    phased_out_items = [key.split('|') for key in list(existing_vendor_item_mappings_set)]
1264 chandransh 274
    write_report("phased_out_items.csv", phased_out_items, sheet, True)
1080 chandransh 275
 
276
    if (not dry_run) and full_update:
2035 rajveer 277
        query_string =  "UPDATE " + str(Item.table) + " SET status=" + str(status.PHASED_OUT) + ", status_description='This item has been phased out'" + ", updatedOn='"+ str(updatedOn) +"'"+\
1080 chandransh 278
                        " WHERE updatedOn <> '" + str(updatedOn) + "' AND hotspotCategory='" + category +"'";
279
        session.execute(query_string, mapper=Item)
626 chandransh 280
        session.commit()
281
 
282
    print "Successfully updated the item list information."
283
 
4725 phani.kuma 284
def check_color_valid(color):
285
    if color is not None:
286
        color = color.strip().lower()
287
        if color != '' and color != 'na' and color != 'blank' and color != '(blank)':
288
            return True
289
    return False
290
 
1264 chandransh 291
def write_report(filename, items, sheet, is_item):
4023 chandransh 292
    '''
293
    Iterates through the items list and writes all the values to the specified
294
    filename in the CSV format. 'is_item' indicates whether the list consists
295
    of row numbers or complete row data.
296
    '''
1080 chandransh 297
    items_writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_ALL)
1264 chandransh 298
    items_writer.writerow(sheet.row_values(0) + ['Old MRP', 'Old DP', 'Old TP'])
299
    if is_item:
4023 chandransh 300
        #The list contains the complete rows.
1264 chandransh 301
        for item in items:
1833 chandransh 302
            print item
1264 chandransh 303
            items_writer.writerow([str(value) for value in item])
304
    else:
4023 chandransh 305
        #The list only has row numbers. We've to fetch the data ourselves.
1264 chandransh 306
        for i in items:
1833 chandransh 307
            print sheet.row_values(i)
1264 chandransh 308
            items_writer.writerow([str(value) for value in sheet.row_values(i)])
1080 chandransh 309
 
626 chandransh 310
def main():
311
    parser = optparse.OptionParser()
312
    parser.add_option("-f", "--file", dest="filename",
313
                   default="ItemList.xls", type="string",
314
                   help="Read the item list from FILE",
315
                   metavar="FILE")
1080 chandransh 316
    parser.add_option("-c", "--category", dest="category",
317
                      type="string",
318
                      help="Update the list only for the products belonging to CATEGORY",
319
                      metavar="CATEGORY")
1356 chandransh 320
    parser.add_option("-v", "--vendor", dest="vendor",
321
                      type="int",
322
                      help="Update the pricing information for VENDOR",
323
                      metavar="VENDOR")
1080 chandransh 324
    parser.add_option("-d", "--dry-run", dest="dry_run",
325
                      action="store_true",
326
                      help="Dry run only reporting on pending changes.Please note that some of the items can be reported twice.")
327
    parser.add_option("-a", "--full", dest="full_update",
328
                      action="store_true",
329
                      help="In a full update, all older items are marked as PHASED_OUT. Also see -pm.")
330
    parser.add_option("-p", "--partial", dest="full_update",
331
                      action="store_false",
332
                      help="In a partial update, older items are left as is. Also see -fm.")
1356 chandransh 333
    parser.add_option("-g", "--product-group", dest="product_group",
334
                      type="string",
335
                      help="Set GROUP as the product group for all items added/updated during this run.",
336
                      metavar="GROUP")
337
    parser.set_defaults(full_update=True, dry_run=False, category="Handsets", vendor=1)
626 chandransh 338
    (options, args) = parser.parse_args()
339
    if len(args) != 0:
340
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
341
    filename = options.filename
1356 chandransh 342
    load_item_data(filename, options.vendor, options.category, options.full_update, options.dry_run, options.product_group)
626 chandransh 343
 
344
if __name__ == '__main__':
345
    main()