Subversion Repositories SmartDukaan

Rev

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