Subversion Repositories SmartDukaan

Rev

Rev 4023 | Rev 4717 | 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 = []
1356 chandransh 37
 
38
    existing_vendor_item_mappings = VendorItemMapping.query.filter_by(vendor=vendor, vendor_category=category).all()
39
    existing_vendor_item_mappings_set = set([mapping.item_key for mapping in existing_vendor_item_mappings])
40
 
626 chandransh 41
    for rownum in range(1, num_rows):
1833 chandransh 42
        print sheet.row_values(rownum)
1356 chandransh 43
        catalog_item_id, category_id = [None, None]
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,\
49
            comments, hotspot_category, unused_feature, xfer_price, weight, start_date, deal_text, deal_value = sheet.row_values(rownum)[0:19]
50
            product_group = supplied_product_group
51
        else:
52
            our_brand, our_model_number, our_color,\
53
            product_group, brand, model_number, model_name, color,\
54
            dp, mrp, mop, sp,\
55
            comments, hotspot_category, unused_feature, xfer_price, weight, start_date, deal_text, deal_value = sheet.row_values(rownum)[0:20]
56
 
1833 chandransh 57
        print product_group
58
 
626 chandransh 59
        if isinstance(model_number, float):
60
            model_number = str(int(model_number))
1810 chandransh 61
 
62
        if our_brand == '':
63
            our_brand = brand
64
        if our_model_number == '':
65
            our_model_number = model_number
66
        if our_color == '':
67
            our_color = color
68
 
1633 chandransh 69
        if sp == '':
70
            sp = mop 
1356 chandransh 71
        item = None
72
        vendor_item_pricing = None
1080 chandransh 73
 
1356 chandransh 74
        key = product_group.strip().lower() + '|' + brand.strip().lower() + '|' + model_number.strip().lower() + '|' + color.strip().lower()
75
        if key in existing_vendor_item_mappings_set:
76
            existing_vendor_item_mappings_set.remove(key)
77
            item = VendorItemMapping.query.filter_by(vendor=vendor, item_key=key, vendor_category=category).one().item
78
 
626 chandransh 79
        if item is None:
1080 chandransh 80
            #print "[ADDING:]{0} {1} {2} {3} to our catalogue.".format(product_group, brand, model_number, color)
81
            new_items.append(rownum)
626 chandransh 82
            item = Item()
2330 rajveer 83
            item.product_group = product_group
84
            item.brand = our_brand
85
            item.model_number = our_model_number
86
            item.model_name = model_name
626 chandransh 87
            item.status = status.IN_PROCESS
2035 rajveer 88
            item.status_description = "This item is in process"
626 chandransh 89
            item.addedOn = updatedOn
1089 chandransh 90
            item.hotspotCategory = category
1356 chandransh 91
 
1506 chandransh 92
            if category == 'Handsets':
93
                item.preferredWarehouse = 1
94
            else:
95
                item.preferredWarehouse = 2
96
 
1356 chandransh 97
            vendor_item_mapping = VendorItemMapping(vendor=vendor, item=item, item_key=key, vendor_category=category)
1359 chandransh 98
            vendor_item_pricing = VendorItemPricing(vendor=vendor, item=item)
99
 
626 chandransh 100
            session.add(item)
1356 chandransh 101
            session.add(vendor_item_mapping)
1359 chandransh 102
            session.add(vendor_item_pricing)
1080 chandransh 103
 
104
            if catalog_item_id !=None and catalog_item_id != "":
105
                #Add category and entity id
106
                item.catalog_item_id = int(catalog_item_id)
107
                item.category = int(category_id)
108
                item.status = status.ACTIVE
2035 rajveer 109
                item.status_description = "This item is active"
1080 chandransh 110
            else:
111
                # Check if a similar item already exists in our database
1810 chandransh 112
                similar_item = Item.query.filter_by(product_group=product_group, brand = our_brand, model_number=our_model_number, hotspotCategory=category).first()
1356 chandransh 113
                print "[SIMILAR ITEM FOUND:] FOR {0} {1} {2} {3}".format(product_group, brand, model_number, color)
114
 
1080 chandransh 115
                if similar_item is None or similar_item.catalog_item_id is None:
116
                    # If there is no similar item in the database from before,
117
                    # use the entity_id_generator
118
                    entity_id = EntityIDGenerator.query.first()
119
                    item.catalog_item_id = entity_id.id + 1
120
                    entity_id.id = entity_id.id  + 1
2330 rajveer 121
 
122
 
1080 chandransh 123
                else:
124
                    #If a similar item already exists for a product group, brand and model_number, set it as same.
125
                    item.catalog_item_id = similar_item.catalog_item_id
126
                    item.category = similar_item.category
1356 chandransh 127
                    item.status = similar_item.status
2035 rajveer 128
                    item.status_description = similar_item.status_description
2330 rajveer 129
                    #Use the same brand, model name and model number as in similar item in database
130
                    item.brand = similar_item.brand
131
                    item.model_name = similar_item.model_name
132
                    item.model_number = similar_item.model_number
626 chandransh 133
        else:
1356 chandransh 134
            # If this item already existed and one of its price parameters has changed
1278 chandransh 135
            # in which case we add it to the list of updated items for reporting.
1965 chandransh 136
            if item.status == status.PHASED_OUT:
137
                item.status = status.IN_PROCESS #Not the ideal choice but we don't know whether content has been generated for it beforehand.
2035 rajveer 138
                item.status_description = "This item is in process"
1356 chandransh 139
            vendor_item_pricing = VendorItemPricing.get_by(vendor=vendor, item=item)
140
            if vendor_item_pricing is None:
141
                vendor_item_pricing = VendorItemPricing(vendor=vendor, item=item)
142
                session.add(vendor_item_pricing)
143
 
1633 chandransh 144
            if item.mrp != mrp or vendor_item_pricing.dealerPrice != dp or vendor_item_pricing.transfer_price != xfer_price or item.sellingPrice != sp:
145
                updated_items.append(sheet.row_values(rownum)[0:19] + [item.mrp, item.dealerPrice, item.transfer_price])
2330 rajveer 146
 
147
        #In future we will provide the option to edit color in CMS
1965 chandransh 148
        item.color = our_color
149
 
1080 chandransh 150
        if category_id !=None and category_id != "":
151
            item.category = int(category_id)
152
 
153
        if dp != "":
154
            item.dealerPrice = dp
155
            item.sellingPrice = dp
1356 chandransh 156
            vendor_item_pricing.dealerPrice = dp
629 rajveer 157
 
1080 chandransh 158
        if mrp != "" and mop != "" and mrp <  mop:
1271 chandransh 159
            raise Exception("[BAD MRP and MOP:] for {0} {1} {2} {3}. MRP={4}. MOP={5}".format(product_group, brand, model_number, color, mrp, mop))
1080 chandransh 160
 
1633 chandransh 161
        if mrp != "" and sp != "" and mrp < sp:
162
            raise Exception("[BAD MRP and SP:] for {0} {1} {2} {3}. MRP={4}. SP={5}".format(product_group, brand, model_number, color, mrp, sp))
163
 
1080 chandransh 164
        if mop != "" and xfer_price != "" and xfer_price > mop:
1271 chandransh 165
            raise Exception("[BAD MOP and TP:] for {0} {1} {2} {3}. TP={4}. MOP={5}".format(product_group, brand, model_number, color, xfer_price, mop))
1320 chandransh 166
#        if mrp != "":
167
#            if item.mrp == None or item.mrp >= mrp:
168
#                item.mrp = mrp
169
#            else:
170
#                raise Exception("[NEW MRP MORE THAN old MRP:] for {0} {1} {2} {3}. Old mrp={4}. New MRP={5}".format(product_group, brand, model_number, color, item.mrp, mrp))
873 rajveer 171
 
1431 chandransh 172
        if mrp != "":
173
            item.mrp = mrp
174
 
629 rajveer 175
        if mop != "":
176
            item.mop = mop
1356 chandransh 177
            vendor_item_pricing.mop = mop
1080 chandransh 178
 
724 chandransh 179
        if xfer_price !="":
180
            item.transfer_price = xfer_price
1356 chandransh 181
            vendor_item_pricing.transfer_price = xfer_price
1080 chandransh 182
 
2088 chandransh 183
        if start_date is not None and start_date != '':
184
            #If a start date has been specified, it takes precedence.
185
            item.startDate = datetime.datetime(*xlrd.xldate_as_tuple(start_date, workbook.datemode))
186
        elif item.startDate == None or item.startDate == '': 
187
            #If start date is not specified and item's start date is not set, set it to current time
1431 chandransh 188
            item.startDate = datetime.datetime.now()
1080 chandransh 189
 
1633 chandransh 190
        item.sellingPrice = sp
1080 chandransh 191
 
629 rajveer 192
        if weight != "":    
193
            item.weight = weight
1080 chandransh 194
 
195
#        item.bestDealText = deal_text
196
#        if deal_value != "":
197
#            item.bestDealValue = deal_value
198
#        item.comments = comments
199
 
626 chandransh 200
        item.updatedOn = updatedOn
724 chandransh 201
 
202
        item_change_log = ItemChangeLog()
203
        item_change_log.new_status = item.status
204
        item_change_log.timestamp = updatedOn
205
        item_change_log.item = item
1080 chandransh 206
 
207
        if not dry_run:
208
            session.commit()
209
 
1264 chandransh 210
    write_report("new_items.csv", new_items, sheet, False)
211
    write_report("updated_items.csv", updated_items, sheet, True)
1356 chandransh 212
    phased_out_items = [key.split('|') for key in list(existing_vendor_item_mappings_set)]
1264 chandransh 213
    write_report("phased_out_items.csv", phased_out_items, sheet, True)
1080 chandransh 214
 
215
    if (not dry_run) and full_update:
2035 rajveer 216
        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 217
                        " WHERE updatedOn <> '" + str(updatedOn) + "' AND hotspotCategory='" + category +"'";
218
        session.execute(query_string, mapper=Item)
626 chandransh 219
        session.commit()
220
 
221
    print "Successfully updated the item list information."
222
 
1264 chandransh 223
def write_report(filename, items, sheet, is_item):
4023 chandransh 224
    '''
225
    Iterates through the items list and writes all the values to the specified
226
    filename in the CSV format. 'is_item' indicates whether the list consists
227
    of row numbers or complete row data.
228
    '''
1080 chandransh 229
    items_writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_ALL)
1264 chandransh 230
    items_writer.writerow(sheet.row_values(0) + ['Old MRP', 'Old DP', 'Old TP'])
231
    if is_item:
4023 chandransh 232
        #The list contains the complete rows.
1264 chandransh 233
        for item in items:
1833 chandransh 234
            print item
1264 chandransh 235
            items_writer.writerow([str(value) for value in item])
236
    else:
4023 chandransh 237
        #The list only has row numbers. We've to fetch the data ourselves.
1264 chandransh 238
        for i in items:
1833 chandransh 239
            print sheet.row_values(i)
1264 chandransh 240
            items_writer.writerow([str(value) for value in sheet.row_values(i)])
1080 chandransh 241
 
626 chandransh 242
def main():
243
    parser = optparse.OptionParser()
244
    parser.add_option("-f", "--file", dest="filename",
245
                   default="ItemList.xls", type="string",
246
                   help="Read the item list from FILE",
247
                   metavar="FILE")
1080 chandransh 248
    parser.add_option("-c", "--category", dest="category",
249
                      type="string",
250
                      help="Update the list only for the products belonging to CATEGORY",
251
                      metavar="CATEGORY")
1356 chandransh 252
    parser.add_option("-v", "--vendor", dest="vendor",
253
                      type="int",
254
                      help="Update the pricing information for VENDOR",
255
                      metavar="VENDOR")
1080 chandransh 256
    parser.add_option("-d", "--dry-run", dest="dry_run",
257
                      action="store_true",
258
                      help="Dry run only reporting on pending changes.Please note that some of the items can be reported twice.")
259
    parser.add_option("-a", "--full", dest="full_update",
260
                      action="store_true",
261
                      help="In a full update, all older items are marked as PHASED_OUT. Also see -pm.")
262
    parser.add_option("-p", "--partial", dest="full_update",
263
                      action="store_false",
264
                      help="In a partial update, older items are left as is. Also see -fm.")
1356 chandransh 265
    parser.add_option("-g", "--product-group", dest="product_group",
266
                      type="string",
267
                      help="Set GROUP as the product group for all items added/updated during this run.",
268
                      metavar="GROUP")
269
    parser.set_defaults(full_update=True, dry_run=False, category="Handsets", vendor=1)
626 chandransh 270
    (options, args) = parser.parse_args()
271
    if len(args) != 0:
272
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
273
    filename = options.filename
1356 chandransh 274
    load_item_data(filename, options.vendor, options.category, options.full_update, options.dry_run, options.product_group)
626 chandransh 275
 
276
if __name__ == '__main__':
277
    main()