Subversion Repositories SmartDukaan

Rev

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