Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
94 ashish 1
'''
2
Created on 23-Mar-2010
3
 
4
@author: ashish
5
'''
6
from elixir import *
7
from shop2020.model.v1.catalog.impl import DataService
122 ashish 8
from shop2020.model.v1.catalog.impl.DataService import Item, \
103 ashish 9
    Warehouse, ItemInventoryHistory, CurrentInventorySnapshot, ItemInfo,\
1368 chandransh 10
    ItemChangeLog, Category, EntityIDGenerator, VendorItemPricing,\
3079 rajveer 11
    VendorItemMapping, Vendor, SimilarItems, ProductNotification
122 ashish 12
from shop2020.thriftpy.model.v1.catalog.ttypes import \
2983 chandransh 13
    InventoryServiceException, status, ItemShippingInfo
2065 ankur.sing 14
from shop2020.model.v1.catalog.impl.Convertors import to_t_item,\
15
    to_t_vendor_item_pricing
94 ashish 16
import datetime
871 chandransh 17
import sys
2286 ankur.sing 18
from shop2020.utils.Utils import log_entry, to_py_date, log_risky_flag
621 chandransh 19
from sqlalchemy import desc, asc
3244 chandransh 20
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
1970 rajveer 21
from shop2020.model.v1.catalog.impl.CategoryManager import CategoryManager
2404 chandransh 22
from sqlalchemy.sql.expression import and_, distinct, func
3086 rajveer 23
from string import Template
24
from shop2020.clients.HelperClient import HelperClient
94 ashish 25
 
26
def initialize():
27
    DataService.initialize()
28
 
29
 
103 ashish 30
def get_all_items(is_active):
31
    if is_active:
766 rajveer 32
        items = Item.query.filter_by(status= status.ACTIVE).all()
103 ashish 33
    else:
766 rajveer 34
        items = Item.query.all()
35
    return items
36
 
103 ashish 37
def get_all_items_by_status(status):
2174 ankur.sing 38
    if status == None:
103 ashish 39
        #return all items
766 rajveer 40
        items = get_all_items(False)
103 ashish 41
    else:
766 rajveer 42
        items = Item.query.filter_by(status=status).all()
43
    return items
103 ashish 44
 
635 rajveer 45
def get_item(item_id):
766 rajveer 46
    item = Item.get_by(id=item_id)
47
    return item
94 ashish 48
 
635 rajveer 49
def get_items_by_catalog_id(catalog_id):
447 rajveer 50
    query = Item.query.filter_by(catalog_item_id=catalog_id)
437 rajveer 51
    try:
635 rajveer 52
        items = query.all()
53
        return get_thrift_item_list(items)
1399 rajveer 54
    except Exception as ex:
55
        print ex
437 rajveer 56
        raise InventoryServiceException(109, "Item not found")
57
 
576 chandransh 58
def is_active(item_id):
2983 chandransh 59
    t_item_shipping_info = ItemShippingInfo()
576 chandransh 60
    try:
635 rajveer 61
        item = get_item(item_id)
2983 chandransh 62
        t_item_shipping_info.isActive = (item.status == status.ACTIVE)
63
        t_item_shipping_info.isRisky = item.risky
64
        t_item_shipping_info.quantity = __get_item_availability(item) 
576 chandransh 65
    except InventoryServiceException:
2983 chandransh 66
        print "[ERROR] Unexpected error:", sys.exc_info()[0]
67
    return t_item_shipping_info
68
 
2035 rajveer 69
def get_item_status_description(itemId):
70
    item = get_item(itemId)
71
    return item.status_description
563 chandransh 72
 
94 ashish 73
def get_Warehouse(warehouse_id):
74
    return Warehouse.get_by(id=warehouse_id)
75
 
122 ashish 76
def get_all_warehouses_by_status(status):
77
    if not status:
766 rajveer 78
        warehouses = Warehouse.query.all()
122 ashish 79
    else:
851 chandransh 80
        warehouses = Warehouse.query.filter_by(status=status).all()
81
    return warehouses
122 ashish 82
 
94 ashish 83
def get_all_warehouses_for_item(item_id):
635 rajveer 84
    item = get_item(item_id)
94 ashish 85
    if not item:
122 ashish 86
        raise InventoryServiceException(108, "Some unforeseen error while obtaining item")
87
    return item.get_all_warehouses
94 ashish 88
 
122 ashish 89
def get_all_items_for_warehouse(warehouse_id):
90
    warehouse = get_Warehouse(warehouse_id)
91
    if not warehouse:
92
        raise InventoryServiceException(108, "bad warehouse")
93
    return warehouse.all_items
94
 
94 ashish 95
def add_warehouse(warehouse):
103 ashish 96
    if not warehouse:
122 ashish 97
        raise InventoryServiceException(108, "Bad warehouse")
103 ashish 98
    if get_Warehouse(warehouse.id):
99
        #warehouse is already present.
122 ashish 100
        raise InventoryServiceException(101, "Warehouse already present")
103 ashish 101
 
94 ashish 102
    ds_warehouse = Warehouse()
103
    ds_warehouse.id = warehouse.id
104
    ds_warehouse.location = warehouse.location
122 ashish 105
    ds_warehouse.status = status.ACTIVE
103 ashish 106
    ds_warehouse.addedOn = datetime.datetime.now()
483 rajveer 107
    ds_warehouse.lastCheckedOn = datetime.datetime.now()
108
    ds_warehouse.tinNumber = warehouse.tinNumber
109
    ds_warehouse.pincode = warehouse.pincode
110
    if warehouse.vendorString:
111
        ds_warehouse.vendorString = warehouse.vendorString
94 ashish 112
    session.commit()
103 ashish 113
    return ds_warehouse.id
94 ashish 114
 
122 ashish 115
def update_item(item):
116
    if not item:
117
        raise InventoryServiceException(108, "Bad item in request")
118
 
119
    if not item.id:
609 chandransh 120
        raise InventoryServiceException(101, "Missing id for update")
122 ashish 121
 
2120 ankur.sing 122
    validate_item_prices(item)
2065 ankur.sing 123
 
635 rajveer 124
    ds_item = get_item(item.id)
122 ashish 125
 
126
    if not ds_item:
609 chandransh 127
        raise InventoryServiceException(101, "Item missing in our database")
122 ashish 128
 
963 chandransh 129
    if item.productGroup:
130
        ds_item.product_group = item.productGroup 
131
    if item.brand:
132
        ds_item.brand = item.brand
511 rajveer 133
    if item.modelNumber:
134
        ds_item.model_number = item.modelNumber
2497 ankur.sing 135
    ds_item.color = item.color
136
    ds_item.model_name = item.modelName
137
    ds_item.category = item.category
138
    ds_item.comments = item.comments
511 rajveer 139
 
2497 ankur.sing 140
    ds_item.catalog_item_id = item.catalogItemId
483 rajveer 141
 
2129 ankur.sing 142
    ds_item.mrp = item.mrp
143
    ds_item.sellingPrice = item.sellingPrice
144
 
2497 ankur.sing 145
    ds_item.mop = item.mop
146
    ds_item.dealerPrice = item.dealerPrice
147
    ds_item.transfer_price = item.transferPrice
148
 
2174 ankur.sing 149
    ds_item.weight = item.weight
2129 ankur.sing 150
 
2358 ankur.sing 151
    if ds_item.status != item.itemStatus:
2402 rajveer 152
        add_status_change_log(ds_item, item.itemStatus)
2358 ankur.sing 153
        ds_item.status = item.itemStatus
2035 rajveer 154
    if item.status_description:
155
        ds_item.status_description = item.status_description
122 ashish 156
 
511 rajveer 157
    if item.startDate:
2116 ankur.sing 158
        ds_item.startDate = to_py_date(item.startDate)
2497 ankur.sing 159
    else:
160
        ds_item.startDate = None
511 rajveer 161
    if item.retireDate:
2116 ankur.sing 162
        ds_item.retireDate = to_py_date(item.retireDate)
2497 ankur.sing 163
    else:
164
        ds_item.retireDate = None
511 rajveer 165
 
2497 ankur.sing 166
    ds_item.feature_id = item.featureId
167
    ds_item.feature_description = item.featureDescription
122 ashish 168
 
2129 ankur.sing 169
    ds_item.bestDealText = item.bestDealText
170
    ds_item.bestDealValue = item.bestDealValue
2065 ankur.sing 171
    ds_item.bestSellingRank = item.bestSellingRank
2497 ankur.sing 172
 
2065 ankur.sing 173
    ds_item.defaultForEntity = item.defaultForEntity
2251 ankur.sing 174
    ds_item.risky = item.risky
2347 ankur.sing 175
    ds_item.updatedOn = datetime.datetime.now()
2065 ankur.sing 176
 
122 ashish 177
    session.commit();
178
    return ds_item.id
94 ashish 179
 
2116 ankur.sing 180
def check_vendor_item_mapping(product_group, brand, model_number, color, vendor_id, vendor_category):
181
    key = product_group.strip().lower() + '|' + brand.strip().lower() + '|' + model_number.strip().lower() + '|' + color.strip().lower()
182
    try:
183
        vim = VendorItemMapping.query.filter_by(vendor_id=vendor_id, item_key=key, vendor_category=vendor_category).one()
184
        return True
185
    except:
186
        return False
187
 
103 ashish 188
def add_item(item):
189
    if not item:
122 ashish 190
        raise InventoryServiceException(108, "Bad item in request")
635 rajveer 191
    if get_item(item.id):
122 ashish 192
        raise InventoryServiceException(101, "Item already exists")
2120 ankur.sing 193
 
194
    validate_item_prices(item)
195
 
103 ashish 196
    ds_item = Item()
963 chandransh 197
    if item.productGroup:
198
        ds_item.product_group = item.productGroup
199
    if item.brand:
200
        ds_item.brand = item.brand
515 rajveer 201
    if item.modelName:
202
        ds_item.model_name = item.modelName
203
    if item.modelNumber:
204
        ds_item.model_number = item.modelNumber
609 chandransh 205
    if item.color:
206
        ds_item.color = item.color
2116 ankur.sing 207
    if item.hotspotCategory:
208
        ds_item.hotspotCategory = item.hotspotCategory
209
        if item.hotspotCategory == 'Handsets':
2403 ankur.sing 210
            ds_item.preferredWarehouse = 1
2116 ankur.sing 211
        else:
2403 ankur.sing 212
            ds_item.preferredWarehouse = 2
2116 ankur.sing 213
 
483 rajveer 214
    if item.category:
215
        ds_item.category = item.category
216
    if item.comments:
217
        ds_item.comments = item.comments
218
 
103 ashish 219
    ds_item.addedOn = datetime.datetime.now()
609 chandransh 220
    ds_item.updatedOn = datetime.datetime.now()
2116 ankur.sing 221
    if item.startDate:
222
        ds_item.startDate = to_py_date(item.startDate)
223
    if item.retireDate:
224
        ds_item.retireDate = to_py_date(item.retireDate)
609 chandransh 225
 
483 rajveer 226
    if item.mrp:
227
        ds_item.mrp = item.mrp
228
    if item.mop:
229
        ds_item.mop = item.mop
230
    if item.sellingPrice:
231
        ds_item.sellingPrice = item.sellingPrice
609 chandransh 232
    if item.dealerPrice:
233
        ds_item.dealerPrice = item.dealerPrice
2116 ankur.sing 234
    if item.transferPrice:
235
        ds_item.transfer_price = item.transferPrice
122 ashish 236
    if item.weight:
237
        ds_item.weight = item.weight
238
 
239
    if item.featureId:
240
        ds_item.feature_id = item.featureId
241
    if item.featureDescription:
242
        ds_item.feature_description = item.featureDescription
243
 
103 ashish 244
    if item.otherInfo:
245
        for k,v in item.otherInfo.iteritems():
246
            info = ItemInfo()
247
            info.key = k
248
            info.value = v
249
            ds_item.iteminfo.append(info)
2116 ankur.sing 250
 
103 ashish 251
    #check if categories present. If yes, add them to system
122 ashish 252
 
609 chandransh 253
    if item.bestDealValue:
254
        ds_item.bestDealValue = item.bestDealValue
255
    if item.bestDealText:
256
        ds_item.bestDealText = item.bestDealText
2116 ankur.sing 257
    if item.bestSellingRank:
258
        ds_item.bestSellingRank = item.bestSellingRank
259
    ds_item.defaultForEntity = item.defaultForEntity
2251 ankur.sing 260
    ds_item.risky = item.risky
609 chandransh 261
 
2116 ankur.sing 262
    # Check if a similar item already exists in our database
263
    similar_item = Item.query.filter_by(product_group=item.productGroup, brand = item.brand, model_number=item.modelNumber, hotspotCategory=item.hotspotCategory).first()
264
    print "[SIMILAR ITEM FOUND:] FOR {0} {1} {2} {3} {4}".format(item.productGroup, item.brand, item.modelNumber, item.hotspotCategory, item.color)
265
 
266
    if similar_item is None or similar_item.catalog_item_id is None:
267
        # If there is no similar item in the database from before,
268
        # use the entity_id_generator
269
        entity_id = EntityIDGenerator.query.first()
270
        ds_item.catalog_item_id = entity_id.id + 1
271
        ds_item.status = status.IN_PROCESS
272
        ds_item.status_description = "This item is in process."
273
        entity_id.id = entity_id.id  + 1
274
    else:
275
        #If a similar item already exists for a product group, brand and model_number, set it as same.
276
        ds_item.catalog_item_id = similar_item.catalog_item_id
277
        ds_item.category = similar_item.category
278
        ds_item.status = similar_item.status
279
        ds_item.status_description = similar_item.status_description
280
 
103 ashish 281
    session.commit();
609 chandransh 282
    return ds_item.id       
103 ashish 283
 
483 rajveer 284
def update_inventory(warehouse_id, timestamp, availability):
285
    warehouse = get_Warehouse(warehouse_id)
286
    if not warehouse:
287
        raise InventoryServiceException(107, "Warehouse? Where?")
288
 
289
    time = datetime.datetime.now()
290
    warehouse.lastCheckedOn = time
291
    warehouse.vendorString = timestamp
1368 chandransh 292
    vendor = warehouse.vendor
2368 ankur.sing 293
    session.commit()
1368 chandransh 294
    for item_key, quantity in availability.iteritems():
483 rajveer 295
        try:
1368 chandransh 296
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
297
            item = vendor_item_mapping.item
494 rajveer 298
        except:
299
            continue  
300
        try:
483 rajveer 301
            item_inventory_history = ItemInventoryHistory()
302
            item_inventory_history.warehouse = warehouse
303
            item_inventory_history.item = item
304
            item_inventory_history.timestamp = time
305
            item_inventory_history.availibility = quantity
306
 
307
            current_inventory_snapshot = CurrentInventorySnapshot.get_by(item=item, warehouse=warehouse)
308
            if not current_inventory_snapshot:
309
                current_inventory_snapshot = CurrentInventorySnapshot()
310
                current_inventory_snapshot.item = item
311
                current_inventory_snapshot.warehouse = warehouse
312
                current_inventory_snapshot.availibility = 0
871 chandransh 313
                current_inventory_snapshot.reserved = 0
483 rajveer 314
            # added the difference in the current inventory    
315
            current_inventory_snapshot.availibility = current_inventory_snapshot.availibility + quantity
316
        except:
317
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
2368 ankur.sing 318
        session.commit() 
319
        check_risky_item(item)
483 rajveer 320
 
94 ashish 321
def get_item_inventoy(item_id):
322
 
323
    inventory = Item.get_by(id=item_id).currentInventory
324
    if not inventory:
122 ashish 325
        raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
94 ashish 326
    return inventory
327
 
635 rajveer 328
def get_item_inventory_by_item_id(item_id):
329
    inventory = Item.get_by(id=item_id).currentInventory
379 ashish 330
    if not inventory:
331
        raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
332
    return inventory
333
 
103 ashish 334
 
335
def retire_warehouse(warehouse_id):
336
    if not warehouse_id:
122 ashish 337
        raise InventoryServiceException(101, "Bad warehouse id")
103 ashish 338
    warehouse = get_Warehouse(warehouse_id)
339
    if not warehouse:
122 ashish 340
        raise InventoryServiceException(108, "warehouse id not present")
341
    warehouse.status = status.DELETED;
103 ashish 342
    session.commit()
343
 
344
def retire_item(item_id):
345
    if not item_id:
122 ashish 346
        raise InventoryServiceException(101, "bad item id")
635 rajveer 347
    item = get_item(item_id)
103 ashish 348
    if not item:
122 ashish 349
        raise InventoryServiceException(108, "item id not present")
350
    item.status = status.PHASED_OUT
351
    item.retireDate = datetime.datetime.now()
103 ashish 352
    session.commit()
122 ashish 353
 
354
#need to implement threads based solution here
103 ashish 355
def start_item_on(item_id, timestamp):
356
    if not item_id:
122 ashish 357
        raise InventoryServiceException(101, "bad item id")
635 rajveer 358
    item = get_item(item_id)
103 ashish 359
    if not item:
122 ashish 360
        raise InventoryServiceException(108, "item id not present")
103 ashish 361
 
122 ashish 362
    item.status = status.ACTIVE
363
    item.startDate = datetime.datetime.fromtimestamp(to_py_date(timestamp))
364
    add_status_change_log(item, status.ACTIVE)
103 ashish 365
    session.commit()
366
 
122 ashish 367
#need to implement threads here
103 ashish 368
def retire_item_on(item_id, timestamp):
369
    if not item_id:
122 ashish 370
        raise InventoryServiceException(101, "bad item id")
635 rajveer 371
    item = get_item(item_id)
103 ashish 372
    if not item:
122 ashish 373
        raise InventoryServiceException(108, "item id not present")
103 ashish 374
 
122 ashish 375
    item.status = status.PHASED_OUT
376
    item.retireDate = datetime.datetime.fromtimestamp(to_py_date(timestamp))
377
    add_status_change_log(item, status.PHASED_OUT)
103 ashish 378
    session.commit()
379
 
380
def add_status_change_log(item, new_status):
381
    item_change_log = ItemChangeLog()
382
    item_change_log.new_status = new_status
383
    item_change_log.old_status = item.status
384
    item_change_log.timestamp = datetime.datetime.now()
385
    item_change_log.item = item
386
    session.commit()
387
 
388
def change_item_status(item_id, new_status):
389
    if not item_id:
122 ashish 390
        raise InventoryServiceException(101, "bad item id")
635 rajveer 391
    item = get_item(item_id)
103 ashish 392
    if not item:
122 ashish 393
        raise InventoryServiceException(108, "item id not present")
2116 ankur.sing 394
    add_status_change_log(item, new_status)
122 ashish 395
    item.status = new_status
2251 ankur.sing 396
    if item.status == status.PHASED_OUT:
397
        item.status_description = "This item has been phased out"
398
    elif item.status == status.DELETED:
399
        item.status_description = "This item has been deleted"
2984 rajveer 400
    elif item.status == status.PAUSED or item.status == status.PAUSED_BY_RISK:
2251 ankur.sing 401
        item.status_description = "This item is currently out of stock"        
402
    elif item.status == status.ACTIVE:
403
        item.status_description = "This item is active"
404
    elif item.status == status.IN_PROCESS:
405
        item.status_description = "This item is in process"
406
    elif item.status == status.CONTENT_COMPLETE:
407
        item.status_description = "This item is in process"
103 ashish 408
    session.commit()
409
 
410
def get_item_availability_for_warehouse(warehouse_id, item_id):
411
    if not warehouse_id:
122 ashish 412
        raise InventoryServiceException(101, "bad warehouse_id")
103 ashish 413
    if not item_id:
122 ashish 414
        raise InventoryServiceException(101, "bad item_id")
103 ashish 415
 
416
    warehouse = get_Warehouse(warehouse_id)
417
    if not warehouse:
122 ashish 418
        raise InventoryServiceException(108, "warehouse does not exist")
635 rajveer 419
    item = get_item(item_id)
504 rajveer 420
 
103 ashish 421
    if not item:
766 rajveer 422
        raise InventoryServiceException(108, "item does not exist")
122 ashish 423
 
494 rajveer 424
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id)
504 rajveer 425
    query = query.filter_by(item_id = item.id)
494 rajveer 426
    try:
427
        current_inventory_snapshot = query.one()
871 chandransh 428
        return current_inventory_snapshot.availibility - current_inventory_snapshot.reserved
494 rajveer 429
    except:
430
        return 0
431
    """
432
    current_inventory_snapshot = CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id == warehouse_id, CurrentInventorySnapshot.item_id == item_id).one()
103 ashish 433
    if not current_inventory_snapshot:
434
        return 0
435
    else:
436
        return current_inventory_snapshot.availibility
494 rajveer 437
    """
643 chandransh 438
 
2368 ankur.sing 439
def check_risky_item(item):
2251 ankur.sing 440
    if not item.risky:
441
        return
2983 chandransh 442
    availability = __get_item_availability(item)
443
    if availability <= 0:
2251 ankur.sing 444
        if item.status == status.ACTIVE:
2984 rajveer 445
            change_item_status(item.id, status.PAUSED_BY_RISK)
2251 ankur.sing 446
    else:
2984 rajveer 447
        if item.status == status.PAUSED_BY_RISK:
2251 ankur.sing 448
            change_item_status(item.id, status.ACTIVE)
2368 ankur.sing 449
    session.commit()
2251 ankur.sing 450
 
2983 chandransh 451
def __get_item_availability(item):
452
    all_inventory = CurrentInventorySnapshot.query.filter_by(item = item).all()
453
    availability = 0
454
    reserved = 0
455
    for currInv in all_inventory:
456
        availability = availability + currInv.availibility
457
        reserved = reserved + currInv.reserved
458
    return availability - reserved
459
 
871 chandransh 460
def reserve_item_in_warehouse(item_id, warehouse_id, quantity):    
461
    if not warehouse_id:
462
        raise InventoryServiceException(101, "bad warehouse_id")
2251 ankur.sing 463
    item = get_item(item_id)
464
    if not item:
871 chandransh 465
        raise InventoryServiceException(101, "bad item_id")
466
 
467
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
468
    try:
469
        current_inventory_snapshot = query.one()
470
        current_inventory_snapshot.reserved = current_inventory_snapshot.reserved + quantity
471
        session.commit()
2368 ankur.sing 472
        check_risky_item(item)
871 chandransh 473
        return True
474
    except:
475
        print "Unexpected error:", sys.exc_info()[0]
476
        return False
477
 
478
def reduce_reservation_count(item_id, warehouse_id, quantity):
479
    if not warehouse_id:
480
        raise InventoryServiceException(101, "bad warehouse_id")
2251 ankur.sing 481
    item = get_item(item_id)
482
    if not item:
871 chandransh 483
        raise InventoryServiceException(101, "bad item_id")
484
 
485
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
486
    try:
487
        current_inventory_snapshot = query.one()
488
        current_inventory_snapshot.reserved = current_inventory_snapshot.reserved - quantity
489
        session.commit()
2368 ankur.sing 490
        check_risky_item(item)
871 chandransh 491
        return True
492
    except:
493
        print "Unexpected error:", sys.exc_info()[0]
494
        return False
495
 
2075 rajveer 496
def mark_item_as_content_complete(entity_id, category, brand, modelName, modelNumber):
2828 rajveer 497
    '''
498
    Get all the items for this entityID and update category, brand, modelName and modelNumber for all.
499
    Update Status for only IN_PROCESS items to CONTENT_COMPLETE
500
    '''
723 chandransh 501
    content_complete_status = status.CONTENT_COMPLETE
2828 rajveer 502
    items = Item.query.filter_by(catalog_item_id=entity_id).all()
723 chandransh 503
    current_timestamp = datetime.datetime.now()
504
    for item in items:
2828 rajveer 505
        if item.status == status.IN_PROCESS:
506
            item.status = content_complete_status
507
            item_change_log = ItemChangeLog()
508
            item_change_log.old_status = item.status
509
            item_change_log.new_status = content_complete_status
510
            item_change_log.timestamp = current_timestamp
511
            item_change_log.item = item
723 chandransh 512
 
2075 rajveer 513
        item.category = category
514
        item.brand = brand
2081 rajveer 515
        item.model_name = modelName
516
        item.model_number = modelNumber
723 chandransh 517
        item.updatedOn = current_timestamp
518
    session.commit()
519
    return True
1294 chandransh 520
 
643 chandransh 521
def get_item_availability_for_location(warehouse_loc, item_id):
522
    if warehouse_loc is None:
523
        raise InventoryServiceException(101, "Bad Warehouse Location")
524
    if not item_id:
1416 chandransh 525
        raise InventoryServiceException(101, "Bad Item id")
643 chandransh 526
 
1416 chandransh 527
    item = Item.get_by(id=item_id)
643 chandransh 528
    warehouses = Warehouse.query.filter_by(logisticsLocation=warehouse_loc).all()
529
    warehouse_ids = [warehouse.id for warehouse in warehouses]
530
    warehouse_retid = -1
531
    global_availability = 0
532
    for warehouse_id in warehouse_ids:
785 rajveer 533
        try:
871 chandransh 534
            current_inventory_snapshot = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id).one()
535
            availability = current_inventory_snapshot.availibility - current_inventory_snapshot.reserved
785 rajveer 536
        except:
537
            availability = 0    
643 chandransh 538
        if availability > global_availability:
539
            warehouse_retid = warehouse_id
540
            global_availability = availability
2341 chandransh 541
 
643 chandransh 542
    if warehouse_retid == -1:
759 chandransh 543
        # This is the case when all warehouses have exhausted their
544
        # inventory of this item or no warehouse is available in this
545
        # location.
1416 chandransh 546
        warehouse_retid = int(item.preferredWarehouse)
2344 chandransh 547
        warehouse = Warehouse.get_by(id=warehouse_retid)
2341 chandransh 548
        try:
549
            current_inventory_snapshot = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_retid, item_id = item_id).one()
550
            global_availability = current_inventory_snapshot.availibility - current_inventory_snapshot.reserved
551
        except:
552
            global_availability = 0
643 chandransh 553
 
2341 chandransh 554
    return [warehouse.logisticsLocation, warehouse_retid, global_availability]
555
 
122 ashish 556
def get_warehouses_for_item(item_id):
643 chandransh 557
 
122 ashish 558
    if not item_id:
559
        raise InventoryServiceException(101, "bad item_id")
635 rajveer 560
    item = get_item(item_id)
122 ashish 561
 
562
    if not item:
563
        raise InventoryServiceException(101, "bad item")
564
 
483 rajveer 565
    warehouses = item.currentInventory.warehouse
501 rajveer 566
    return warehouses
567
 
2404 chandransh 568
def get_child_categories(category):
569
    cm = CategoryManager()
2621 varun.gupt 570
    cat = cm.getCategory(category)
571
    return cat.children_category_ids if cat else None
2404 chandransh 572
 
626 chandransh 573
def get_best_sellers(start_index, stop_index, category=-1):
2404 chandransh 574
    '''
575
    Returns the Best Sellers between the start and the stop index in the given category
576
    '''
1926 rajveer 577
    query = get_best_sellers_query(category, None)
1098 chandransh 578
    best_sellers = query.all()[start_index:stop_index]
621 chandransh 579
    return get_thrift_item_list(best_sellers)
580
 
2093 chandransh 581
def get_best_sellers_count(category=-1):
2404 chandransh 582
    '''
583
    Returns the number of best sellers in the given category
584
    '''
1926 rajveer 585
    count = get_best_sellers_query(category, None).count()
1120 rajveer 586
    if count is None:
587
        count = 0
766 rajveer 588
    return count
621 chandransh 589
 
1926 rajveer 590
def get_best_sellers_catalog_ids(start_index, stop_index, brand, category=-1):
2404 chandransh 591
    '''
592
    Returns the Best sellers for the given brand and category between the start and the stop index.
593
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
594
    '''
1926 rajveer 595
    query = get_best_sellers_query(category, brand)
1098 chandransh 596
    best_sellers = query.all()[start_index:stop_index]
621 chandransh 597
    return [item.catalog_item_id for item in best_sellers]
1970 rajveer 598
 
1926 rajveer 599
def get_best_sellers_query(category, brand):
2404 chandransh 600
    '''
601
    Returns the query to be used for getting Best Sellers.
602
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
603
    '''
1098 chandransh 604
    query = Item.query.filter_by(status=status.ACTIVE).filter(Item.bestSellingRank != None)
626 chandransh 605
    if category != -1:
1970 rajveer 606
        all_categories = [category]
607
        child_categories = get_child_categories(category)
608
        if child_categories is not None:
609
            all_categories = all_categories + child_categories 
610
        query = query.filter(Item.category.in_(all_categories))
1926 rajveer 611
    if brand is not None:
612
        query = query.filter_by(brand=brand)
1098 chandransh 613
    query = query.order_by(asc(Item.bestSellingRank))
621 chandransh 614
    return query
609 chandransh 615
 
1098 chandransh 616
def get_best_deals(category=-1):
2404 chandransh 617
    '''
618
    Returns the Best deals in the given category. Ignores the category if it's passed as -1.
619
    '''
620
    query = get_best_deals_query(Item, category, None)
1098 chandransh 621
    items = query.all()
609 chandransh 622
    return get_thrift_item_list(items)
623
 
1098 chandransh 624
def get_best_deals_count(category=-1):
2404 chandransh 625
    '''
626
    Returns the count of best deals in the given category.
627
    Ignores the category if it's -1.
628
    '''
629
    count = get_best_deals_counting_query(func.count(distinct(Item.catalog_item_id)), category, None).scalar()
1120 rajveer 630
    if count is None:
631
        count = 0
766 rajveer 632
    return count
501 rajveer 633
 
1926 rajveer 634
def get_best_deals_catalog_ids(start_index, stop_index, brand, category=-1):
2404 chandransh 635
    '''
636
    Returns the catalog_item_ids of best deal items for the given brand and category.
637
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
638
    '''
639
    query = get_best_deals_query(Item, category, brand)
1098 chandransh 640
    best_deal_items = query.all()[start_index:stop_index]
641
    return [item.catalog_item_id for item in best_deal_items]
642
 
2404 chandransh 643
def get_best_deals_counting_query(obj, category, brand):
644
    '''
645
    Returns the query to be used to select the best deals in the given brand and category.
646
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
647
    '''
648
    query = session.query(obj).filter_by(status=status.ACTIVE).filter(Item.bestDealValue != None)
626 chandransh 649
    if category != -1:
1970 rajveer 650
        all_categories = [category]
651
        child_categories = get_child_categories(category)
652
        if child_categories is not None:
653
            all_categories = all_categories + child_categories 
654
        query = query.filter(Item.category.in_(all_categories))
1926 rajveer 655
    if brand is not None:
656
        query = query.filter_by(brand=brand)
2404 chandransh 657
    return query
658
 
659
def get_best_deals_query(obj, category, brand):
660
    '''
661
    Returns the query to be used to get the best deals in the given category and brand.
662
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
663
    '''
664
    query = get_best_deals_counting_query(obj, category, brand)
1098 chandransh 665
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.bestDealValue))
666
    return query
609 chandransh 667
 
1098 chandransh 668
def get_latest_arrivals(limit, category=-1):
2404 chandransh 669
    '''
670
    Returns up to limit number of Latest Arrivals in the given category.
671
    '''
2975 chandransh 672
    categories = []
673
    if category != -1:
674
        categories = [category]
675
    query = get_latest_arrivals_query(Item, categories, None)
1098 chandransh 676
    items = query.all()[0:limit]
609 chandransh 677
    return get_thrift_item_list(items)
598 chandransh 678
 
1098 chandransh 679
def get_latest_arrivals_count(limit, category=-1):
2404 chandransh 680
    '''
681
    Returns the number of latest arrivals which will be displayed on the website.
3016 chandransh 682
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 683
    '''
2975 chandransh 684
    categories = []
685
    if category != -1:
686
        categories = [category]
687
    count = get_latest_arrivals_counting_query(func.count(distinct(Item.catalog_item_id)), categories, None).scalar()
1120 rajveer 688
    if count is None:
689
        count = 0
690
    count = min(count, limit)
766 rajveer 691
    return count
602 chandransh 692
 
2975 chandransh 693
def get_latest_arrivals_catalog_ids(start_index, stop_index, brand, categories=[]):
2404 chandransh 694
    '''
695
    Returns the catalog_item_ids of the latest arrivals between the start and the stop index
3016 chandransh 696
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 697
    '''
2975 chandransh 698
    query = get_latest_arrivals_query(Item, categories, brand)
1098 chandransh 699
    latest_arrivals = query.all()[start_index:stop_index]
700
    return [item.catalog_item_id for item in latest_arrivals]
701
 
2975 chandransh 702
def get_latest_arrivals_counting_query(obj, categories, brand):
2404 chandransh 703
    '''
704
    Returns the query to be used to count Latest arrivals.
3016 chandransh 705
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 706
    '''
707
    query = session.query(obj).filter_by(status=status.ACTIVE)
2975 chandransh 708
 
709
    all_categories = []
710
    for category in categories:
711
        all_categories.append(category)
1970 rajveer 712
        child_categories = get_child_categories(category)
2975 chandransh 713
        if child_categories:
714
            all_categories = all_categories + child_categories
715
    if all_categories: 
1970 rajveer 716
        query = query.filter(Item.category.in_(all_categories))
2975 chandransh 717
 
1926 rajveer 718
    if brand is not None:
719
        query = query.filter_by(brand=brand)
2404 chandransh 720
    return query
721
 
2975 chandransh 722
def get_latest_arrivals_query(obj, categories, brand):
2404 chandransh 723
    '''
724
    Returns the query to be used to retrieve Latest Arrivals.
725
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
726
    '''
2975 chandransh 727
    query = get_latest_arrivals_counting_query(obj, categories, brand)
1098 chandransh 728
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.startDate))
729
    return query
609 chandransh 730
 
731
def get_thrift_item_list(items):
1098 chandransh 732
    return [to_t_item(item) for item in items if item != None]
635 rajveer 733
 
1155 rajveer 734
def generate_new_entity_id():
735
    generator =  EntityIDGenerator.query.one()
736
    id = generator.id + 1
737
    generator.id = id
738
    session.commit()
739
    return id
740
 
635 rajveer 741
def put_category_object(object):
742
    category = Category.get_by(id=1)
743
    if category is None:
744
        category = Category()
745
    category.object = object    
746
    session.commit()
747
    return True
748
 
749
def get_category_object():
766 rajveer 750
    object = Category.get_by(id=1).object
751
    return object
752
 
1341 chandransh 753
def get_item_pricing(item_id, warehouse_id):
754
    item = Item.query.filter_by(id=item_id).first()
755
    if item is None:
756
        raise InventoryServiceException(101, "Bad Item")
757
 
758
    warehouse = get_Warehouse(warehouse_id)
759
    if not warehouse:
760
        raise InventoryServiceException(108, "Bad Warehouse")
761
    vendor = warehouse.vendor
762
 
763
    try:
764
        item_pricing = VendorItemPricing.query.filter_by(vendor=vendor, item=item).one()
1347 chandransh 765
        return item_pricing
3244 chandransh 766
    except MultipleResultsFound:
1341 chandransh 767
        raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
3244 chandransh 768
    except NoResultFound:
1341 chandransh 769
        raise InventoryServiceException(111, "Missing pricing information for Vendor: " + vendor.name + " and Item: " + str(item_id))
770
 
1970 rajveer 771
def add_category(t_category):
772
    category = Category.get_by(id=t_category.id)
773
    if category is None:
774
        category = Category()
775
    category.id = t_category.id 
776
    category.label = t_category.label
777
    category.description = t_category.description
778
    category.parent_category_id = t_category.parent_category_id 
779
    session.commit()
780
    return True
781
 
782
def get_category(id):
783
    return Category.query.filter_by(id=id).first()
784
 
785
def get_all_categories():
786
    return Category.query.all()
787
 
1991 ankur.sing 788
 
789
def get_all_item_pricing(item_id):
790
    item = Item.query.filter_by(id=item_id).first()
791
    if item is None:
792
        raise InventoryServiceException(101, "Bad Item")
793
    item_pricing = VendorItemPricing.query.filter_by(item=item).all()
794
    return item_pricing
795
 
2116 ankur.sing 796
def get_item_mappings(item_id):
797
    item = Item.query.filter_by(id=item_id).first()
798
    if item is None:
799
        raise InventoryServiceException(101, "Bad Item")
800
    item_mappings = VendorItemMapping.query.filter_by(item=item).all()
801
    return item_mappings
802
 
803
def add_vendor_pricing(vendorItemPricing):
1991 ankur.sing 804
    if not vendorItemPricing:
805
        raise InventoryServiceException(108, "Bad vendorItemPricing in request")
806
    vendorId = vendorItemPricing.vendorId
807
    itemId = vendorItemPricing.itemId
808
 
809
    try:
810
        vendor = Vendor.query.filter_by(id=vendorId).one()
811
    except:
812
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
813
 
814
    try:
815
        item = Item.query.filter_by(id=itemId).one()
816
    except:
817
        raise InventoryServiceException(101, "Item not found for vendorId " + str(itemId))
818
 
2120 ankur.sing 819
    validate_vendor_prices(to_t_item(item), vendorItemPricing)
2065 ankur.sing 820
 
1991 ankur.sing 821
    try:
822
        ds_vendorItemPricing = VendorItemPricing.query.filter(and_(VendorItemPricing.vendor==vendor, VendorItemPricing.item==item)).one()
823
    except:
2116 ankur.sing 824
        ds_vendorItemPricing = VendorItemPricing()
825
        ds_vendorItemPricing.vendor = vendor
826
        ds_vendorItemPricing.item = item
1991 ankur.sing 827
 
828
    if vendorItemPricing.mop:
829
        ds_vendorItemPricing.mop = vendorItemPricing.mop
830
    if vendorItemPricing.dealerPrice:
831
        ds_vendorItemPricing.dealerPrice = vendorItemPricing.dealerPrice
832
    if vendorItemPricing.transferPrice:
2065 ankur.sing 833
        ds_vendorItemPricing.transfer_price = vendorItemPricing.transferPrice
1991 ankur.sing 834
 
835
    session.commit()
836
    return
837
 
2358 ankur.sing 838
def add_vendor_item_mapping(key, vendorItemMapping):
2116 ankur.sing 839
    if not vendorItemMapping:
840
        raise InventoryServiceException(108, "Bad vendorItemMapping in request")
841
    vendorId = vendorItemMapping.vendorId
842
    itemId = vendorItemMapping.itemId
843
 
844
    try:
845
        vendor = Vendor.query.filter_by(id=vendorId).one()
846
    except:
847
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
848
 
849
    try:
850
        item = Item.query.filter_by(id=itemId).one()
851
    except:
852
        raise InventoryServiceException(101, "Item not found for vendorId " + str(itemId))
853
 
854
    try:
2358 ankur.sing 855
        ds_vendorItemMapping = VendorItemMapping.query.filter(and_(VendorItemMapping.vendor==vendor, VendorItemMapping.item==item, VendorItemMapping.item_key==key)).one()
2116 ankur.sing 856
    except:
857
        ds_vendorItemMapping = VendorItemMapping()
858
        ds_vendorItemMapping.vendor = vendor
859
        ds_vendorItemMapping.item = item
2497 ankur.sing 860
    ds_vendorItemMapping.vendor_category = vendorItemMapping.vendorCategory
2116 ankur.sing 861
    ds_vendorItemMapping.item_key = vendorItemMapping.itemKey
862
 
863
    session.commit()
864
    return
865
 
2120 ankur.sing 866
def validate_item_prices(item):
2129 ankur.sing 867
    if item.mrp == None or item.sellingPrice == None or item.mrp == "" or item.sellingPrice == "":
868
        return
869
    if item.mrp < item.sellingPrice:
2120 ankur.sing 870
        print "[BAD MRP and SP:] for {0} {1} {2} {3}. MRP={4}, SP={5}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(item.mrp), str(item.sellingPrice))
871
        raise InventoryServiceException(101, "[BAD MRP and SP:] for {0} {1} {2} {3}. MRP={4}, SP={5}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(item.mrp), str(item.sellingPrice)))
2065 ankur.sing 872
    return
2120 ankur.sing 873
 
874
def validate_vendor_prices(item, vendorPrices):
2129 ankur.sing 875
    if item.mrp != None and item.mrp != "" and vendorPrices.mop != "" and item.mrp <  vendorPrices.mop:
2120 ankur.sing 876
        print "[BAD MRP and MOP:] for {0} {1} {2} {3}. MRP={4}. MOP={5}, Vendor={6}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(item.mrp), str(vendorPrices.mop), str(vendorPrices.vendorId))
877
        raise InventoryServiceException(101, "[BAD MRP and MOP:] for {0} {1} {2} {3}. MRP={4}. MOP={5}, Vendor={6}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(item.mrp), str(vendorPrices.mop), str(vendorPrices.vendorId)))
878
    if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
879
        print "[BAD MOP and TP:] for {0} {1} {2} {3}. TP={4}. MOP={5}, Vendor={6}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(vendorPrices.transferPrice), str(vendorPrices.mop), str(vendorPrices.vendorId))
880
        raise InventoryServiceException(101, "[BAD MOP and TP:] for {0} {1} {2} {3}. TP={4}. MOP={5}, Vendor={6}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(vendorPrices.transferPrice), str(vendorPrices.mop), str(vendorPrices.vendorId)))
881
    return
2065 ankur.sing 882
 
883
def get_all_vendors():
884
    return Vendor.query.all()
885
 
2116 ankur.sing 886
def check_similar_item(product_group, brand, model_number, color):
2129 ankur.sing 887
    query = Item.query
2428 ankur.sing 888
    query = query.filter_by(product_group=product_group)
889
    query = query.filter_by(brand=brand)
890
    query = query.filter_by(model_number=model_number)
2129 ankur.sing 891
    if color:
892
        query = query.filter_by(color=color)
893
    item = query.first()
2116 ankur.sing 894
    if item is None:
895
        return 0
896
    else:
897
        return item.id
2286 ankur.sing 898
 
899
def change_risky_flag(item_id, risky):
900
    item = get_item(item_id)
901
    if not item:
902
        raise InventoryServiceException(101, "Item missing in our database")
903
    try:
904
        log_risky_flag(item_id, risky)
905
    except:
906
        print "Not able to log risky flag change"
907
    item.risky = risky
2368 ankur.sing 908
    if not risky and item.status == status.PAUSED:
909
        change_item_status(item.id, status.ACTIVE)
2286 ankur.sing 910
    session.commit()
2368 ankur.sing 911
    check_risky_item(item)
2286 ankur.sing 912
 
2358 ankur.sing 913
def get_items_by_vendor_category(vendor_category):
914
    if not vendor_category:
915
        raise InventoryServiceException(101, "Invalid vendor category in request")
916
    query = Item.query.filter(and_(Item.hotspotCategory==vendor_category, Item.status != status.PHASED_OUT))
917
    items = query.all()
918
    return items
2116 ankur.sing 919
 
2358 ankur.sing 920
def get_risky_items():
921
    items = Item.query.filter_by(risky=True).all()
922
    return items
3008 rajveer 923
 
2809 rajveer 924
def get_similar_items_catalog_ids(start_index, stop_index, itemId):
3008 rajveer 925
    query = SimilarItems.query.filter_by(item_id=itemId).limit(stop_index-start_index)
926
    similar_items = query.all()
2809 rajveer 927
    return [item.catalog_item_id for item in similar_items]
928
 
3079 rajveer 929
def add_product_notification(itemId, email):
930
    try:
931
        product_notification = ProductNotification()
932
        product_notification.email = email
933
        product_notification.item_id = itemId
934
        product_notification.addedOn = datetime.datetime.now()
935
        session.commit()
936
        return True
937
    except:
938
        return False
3086 rajveer 939
 
940
 
941
def send_product_notifications():
942
    product_notifications = ProductNotification.query.all()
943
    for product_notification in product_notifications:
944
        item = product_notification.item
945
        availability = __get_item_availability(item)
946
        if availability > 0:
947
            __enque_product_notification_email(product_notification.email, __get_product_name(item) , product_notification.addedOn, __get_product_url(item), item.id)
948
            product_notification.delete()
949
    session.commit()
950
    return True
951
 
952
def __get_product_name(item):
953
    product_name = item.brand + " " + item.model_name + " " + item.model_number
954
    color = item.color
955
    if color is not None and color != 'NA':
956
        product_name = product_name + " (" + color + ")"
3201 rajveer 957
    product_name = product_name.replace("  "," ")
3086 rajveer 958
    return product_name
959
 
960
 
961
def __get_product_url(item):
962
    product_url = "http://www.saholic.com/mobile-phones/" + item.brand + "-" + item.model_name + "-" + item.model_number + "-" + str(item.catalog_item_id)
963
    product_url = product_url.replace("--","-")
964
    product_url = product_url.replace(" ","")
965
    return product_url
966
 
967
 
968
 
969
def __enque_product_notification_email(email, product, date, url, itemId):
970
 
971
    html = """
972
        <html>
973
        <body>
974
        <div>
975
        <p>
976
            Hi,<br /><br />
977
            The product requested by you on $date is now available on saholic.com.
978
        </p>
979
 
980
        <p>    
981
        <strong>Product: $product </strong>
982
        </p>
983
 
984
        <p>
985
        Click the link below to visit the product: 
986
        <br/>
987
        $url
988
        </p>
989
        <p>
990
        Regards,<br/>
991
        Saholic Customer Support Team<br/>
992
        www.saholic.com<br/>
993
        Email: help@saholic.com<br/>
994
        </p>
995
        </div>
996
        </body>
997
        </html>
998
        """
999
 
1000
    html = Template(html).substitute(dict(product=product,date=date,url=url))
3079 rajveer 1001
 
3086 rajveer 1002
    try:
1003
        helper_client = HelperClient().get_client()
1004
        helper_client.saveUserEmailForSending(email, "", "Product requested by you is available now.", html, str(itemId), "ProductNotification")
1005
    except Exception as e:
1006
        print e
1007
 
1008
 
766 rajveer 1009
def close_session():
1010
    if session.is_active:
1011
        print "session is active. closing it."
1399 rajveer 1012
        session.close()