Subversion Repositories SmartDukaan

Rev

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