Subversion Repositories SmartDukaan

Rev

Rev 2975 | Rev 2984 | 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 \
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
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):
2983 chandransh 56
    t_item_shipping_info = ItemShippingInfo()
576 chandransh 57
    try:
635 rajveer 58
        item = get_item(item_id)
2983 chandransh 59
        t_item_shipping_info.isActive = (item.status == status.ACTIVE)
60
        t_item_shipping_info.isRisky = item.risky
61
        t_item_shipping_info.quantity = __get_item_availability(item) 
576 chandransh 62
    except InventoryServiceException:
2983 chandransh 63
        print "[ERROR] Unexpected error:", sys.exc_info()[0]
64
    return t_item_shipping_info
65
 
2035 rajveer 66
def get_item_status_description(itemId):
67
    item = get_item(itemId)
68
    return item.status_description
563 chandransh 69
 
94 ashish 70
def get_Warehouse(warehouse_id):
71
    return Warehouse.get_by(id=warehouse_id)
72
 
122 ashish 73
def get_all_warehouses_by_status(status):
74
    if not status:
766 rajveer 75
        warehouses = Warehouse.query.all()
122 ashish 76
    else:
851 chandransh 77
        warehouses = Warehouse.query.filter_by(status=status).all()
78
    return warehouses
122 ashish 79
 
94 ashish 80
def get_all_warehouses_for_item(item_id):
635 rajveer 81
    item = get_item(item_id)
94 ashish 82
    if not item:
122 ashish 83
        raise InventoryServiceException(108, "Some unforeseen error while obtaining item")
84
    return item.get_all_warehouses
94 ashish 85
 
122 ashish 86
def get_all_items_for_warehouse(warehouse_id):
87
    warehouse = get_Warehouse(warehouse_id)
88
    if not warehouse:
89
        raise InventoryServiceException(108, "bad warehouse")
90
    return warehouse.all_items
91
 
94 ashish 92
def add_warehouse(warehouse):
103 ashish 93
    if not warehouse:
122 ashish 94
        raise InventoryServiceException(108, "Bad warehouse")
103 ashish 95
    if get_Warehouse(warehouse.id):
96
        #warehouse is already present.
122 ashish 97
        raise InventoryServiceException(101, "Warehouse already present")
103 ashish 98
 
94 ashish 99
    ds_warehouse = Warehouse()
100
    ds_warehouse.id = warehouse.id
101
    ds_warehouse.location = warehouse.location
122 ashish 102
    ds_warehouse.status = status.ACTIVE
103 ashish 103
    ds_warehouse.addedOn = datetime.datetime.now()
483 rajveer 104
    ds_warehouse.lastCheckedOn = datetime.datetime.now()
105
    ds_warehouse.tinNumber = warehouse.tinNumber
106
    ds_warehouse.pincode = warehouse.pincode
107
    if warehouse.vendorString:
108
        ds_warehouse.vendorString = warehouse.vendorString
94 ashish 109
    session.commit()
103 ashish 110
    return ds_warehouse.id
94 ashish 111
 
122 ashish 112
def update_item(item):
113
    if not item:
114
        raise InventoryServiceException(108, "Bad item in request")
115
 
116
    if not item.id:
609 chandransh 117
        raise InventoryServiceException(101, "Missing id for update")
122 ashish 118
 
2120 ankur.sing 119
    validate_item_prices(item)
2065 ankur.sing 120
 
635 rajveer 121
    ds_item = get_item(item.id)
122 ashish 122
 
123
    if not ds_item:
609 chandransh 124
        raise InventoryServiceException(101, "Item missing in our database")
122 ashish 125
 
963 chandransh 126
    if item.productGroup:
127
        ds_item.product_group = item.productGroup 
128
    if item.brand:
129
        ds_item.brand = item.brand
511 rajveer 130
    if item.modelNumber:
131
        ds_item.model_number = item.modelNumber
2497 ankur.sing 132
    ds_item.color = item.color
133
    ds_item.model_name = item.modelName
134
    ds_item.category = item.category
135
    ds_item.comments = item.comments
511 rajveer 136
 
2497 ankur.sing 137
    ds_item.catalog_item_id = item.catalogItemId
483 rajveer 138
 
2129 ankur.sing 139
    ds_item.mrp = item.mrp
140
    ds_item.sellingPrice = item.sellingPrice
141
 
2497 ankur.sing 142
    ds_item.mop = item.mop
143
    ds_item.dealerPrice = item.dealerPrice
144
    ds_item.transfer_price = item.transferPrice
145
 
2174 ankur.sing 146
    ds_item.weight = item.weight
2129 ankur.sing 147
 
2358 ankur.sing 148
    if ds_item.status != item.itemStatus:
2402 rajveer 149
        add_status_change_log(ds_item, item.itemStatus)
2358 ankur.sing 150
        ds_item.status = item.itemStatus
2035 rajveer 151
    if item.status_description:
152
        ds_item.status_description = item.status_description
122 ashish 153
 
511 rajveer 154
    if item.startDate:
2116 ankur.sing 155
        ds_item.startDate = to_py_date(item.startDate)
2497 ankur.sing 156
    else:
157
        ds_item.startDate = None
511 rajveer 158
    if item.retireDate:
2116 ankur.sing 159
        ds_item.retireDate = to_py_date(item.retireDate)
2497 ankur.sing 160
    else:
161
        ds_item.retireDate = None
511 rajveer 162
 
2497 ankur.sing 163
    ds_item.feature_id = item.featureId
164
    ds_item.feature_description = item.featureDescription
122 ashish 165
 
2129 ankur.sing 166
    ds_item.bestDealText = item.bestDealText
167
    ds_item.bestDealValue = item.bestDealValue
2065 ankur.sing 168
    ds_item.bestSellingRank = item.bestSellingRank
2497 ankur.sing 169
 
2065 ankur.sing 170
    ds_item.defaultForEntity = item.defaultForEntity
2251 ankur.sing 171
    ds_item.risky = item.risky
2809 rajveer 172
    ds_item.similarityIndex = item.similarityIndex
2347 ankur.sing 173
    ds_item.updatedOn = datetime.datetime.now()
2065 ankur.sing 174
 
122 ashish 175
    session.commit();
176
    return ds_item.id
94 ashish 177
 
2116 ankur.sing 178
def check_vendor_item_mapping(product_group, brand, model_number, color, vendor_id, vendor_category):
179
    key = product_group.strip().lower() + '|' + brand.strip().lower() + '|' + model_number.strip().lower() + '|' + color.strip().lower()
180
    try:
181
        vim = VendorItemMapping.query.filter_by(vendor_id=vendor_id, item_key=key, vendor_category=vendor_category).one()
182
        return True
183
    except:
184
        return False
185
 
103 ashish 186
def add_item(item):
187
    if not item:
122 ashish 188
        raise InventoryServiceException(108, "Bad item in request")
635 rajveer 189
    if get_item(item.id):
122 ashish 190
        raise InventoryServiceException(101, "Item already exists")
2120 ankur.sing 191
 
192
    validate_item_prices(item)
193
 
103 ashish 194
    ds_item = Item()
963 chandransh 195
    if item.productGroup:
196
        ds_item.product_group = item.productGroup
197
    if item.brand:
198
        ds_item.brand = item.brand
515 rajveer 199
    if item.modelName:
200
        ds_item.model_name = item.modelName
201
    if item.modelNumber:
202
        ds_item.model_number = item.modelNumber
609 chandransh 203
    if item.color:
204
        ds_item.color = item.color
2116 ankur.sing 205
    if item.hotspotCategory:
206
        ds_item.hotspotCategory = item.hotspotCategory
207
        if item.hotspotCategory == 'Handsets':
2403 ankur.sing 208
            ds_item.preferredWarehouse = 1
2116 ankur.sing 209
        else:
2403 ankur.sing 210
            ds_item.preferredWarehouse = 2
2116 ankur.sing 211
 
483 rajveer 212
    if item.category:
213
        ds_item.category = item.category
214
    if item.comments:
215
        ds_item.comments = item.comments
216
 
103 ashish 217
    ds_item.addedOn = datetime.datetime.now()
609 chandransh 218
    ds_item.updatedOn = datetime.datetime.now()
2116 ankur.sing 219
    if item.startDate:
220
        ds_item.startDate = to_py_date(item.startDate)
221
    if item.retireDate:
222
        ds_item.retireDate = to_py_date(item.retireDate)
609 chandransh 223
 
483 rajveer 224
    if item.mrp:
225
        ds_item.mrp = item.mrp
226
    if item.mop:
227
        ds_item.mop = item.mop
228
    if item.sellingPrice:
229
        ds_item.sellingPrice = item.sellingPrice
609 chandransh 230
    if item.dealerPrice:
231
        ds_item.dealerPrice = item.dealerPrice
2116 ankur.sing 232
    if item.transferPrice:
233
        ds_item.transfer_price = item.transferPrice
122 ashish 234
    if item.weight:
235
        ds_item.weight = item.weight
236
 
237
    if item.featureId:
238
        ds_item.feature_id = item.featureId
239
    if item.featureDescription:
240
        ds_item.feature_description = item.featureDescription
241
 
103 ashish 242
    if item.otherInfo:
243
        for k,v in item.otherInfo.iteritems():
244
            info = ItemInfo()
245
            info.key = k
246
            info.value = v
247
            ds_item.iteminfo.append(info)
2116 ankur.sing 248
 
103 ashish 249
    #check if categories present. If yes, add them to system
122 ashish 250
 
609 chandransh 251
    if item.bestDealValue:
252
        ds_item.bestDealValue = item.bestDealValue
253
    if item.bestDealText:
254
        ds_item.bestDealText = item.bestDealText
2116 ankur.sing 255
    if item.bestSellingRank:
256
        ds_item.bestSellingRank = item.bestSellingRank
257
    ds_item.defaultForEntity = item.defaultForEntity
2251 ankur.sing 258
    ds_item.risky = item.risky
2809 rajveer 259
    if item.similarityIndex:
260
        ds_item.similarityIndex = item.similarityIndex
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"
400
    elif item.status == status.PAUSED:
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:
445
            change_item_status(item.id, status.PAUSED)
446
    else:
447
        if item.status == status.PAUSED:
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.
682
    Ignores the category if it's passed as -1.
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
696
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
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.
705
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
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
1341 chandransh 766
    except sqlalchemy.orm.exc.MultipleResultsFound:
767
        raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
768
    except sqlalchemy.orm.exc.NoResultFound:
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
923
 
2809 rajveer 924
def get_similar_items_catalog_ids(start_index, stop_index, itemId):
925
    similarity_index = Item.get_by(id = itemId).similarityIndex
926
    if similarity_index is None:
927
        return []
928
    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)
929
    similar_items = query.all()[start_index:stop_index]
930
    return [item.catalog_item_id for item in similar_items]
931
 
766 rajveer 932
def close_session():
933
    if session.is_active:
934
        print "session is active. closing it."
1399 rajveer 935
        session.close()