Subversion Repositories SmartDukaan

Rev

Rev 4310 | Rev 4317 | 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,\
3557 rajveer 11
    VendorItemMapping, Vendor, SimilarItems, ProductNotification, Source, SourceItemPricing
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,\
3557 rajveer 15
    to_t_vendor_item_pricing, to_t_source
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
3872 chandransh 22
from sqlalchemy.sql.expression import and_, or_, distinct, func
3086 rajveer 23
from string import Template
24
from shop2020.clients.HelperClient import HelperClient
3924 rajveer 25
import urllib2
26
from urllib2 import HTTPBasicAuthHandler
27
from shop2020.config.client.ConfigClient import ConfigClient
94 ashish 28
 
29
def initialize():
30
    DataService.initialize()
31
 
3849 chandransh 32
def get_all_items_by_status(status, offset=0, limit=None):
33
    query = Item.query
34
    if status:
35
        query = query.filter_by(status=status)
36
    query = query.order_by(Item.product_group, Item.brand, Item.model_number, Item.model_name).offset(offset)
37
    if limit:
38
        query = query.limit(limit)
39
    items = query.all()
40
    return items
41
 
42
def get_all_items(is_active, offset=0, limit=None):
103 ashish 43
    if is_active:
3849 chandransh 44
        items = get_all_items_by_status(status.ACTIVE, offset, limit)
103 ashish 45
    else:
3849 chandransh 46
        items = get_all_items_by_status(None, offset, limit)
766 rajveer 47
    return items
48
 
3849 chandransh 49
def get_item_count_by_status(use_status, status):
50
    if use_status:
51
        return Item.query.filter_by(status=status).count()
103 ashish 52
    else:
3849 chandransh 53
        return Item.query.count()
103 ashish 54
 
635 rajveer 55
def get_item(item_id):
766 rajveer 56
    item = Item.get_by(id=item_id)
57
    return item
94 ashish 58
 
635 rajveer 59
def get_items_by_catalog_id(catalog_id):
447 rajveer 60
    query = Item.query.filter_by(catalog_item_id=catalog_id)
437 rajveer 61
    try:
635 rajveer 62
        items = query.all()
63
        return get_thrift_item_list(items)
1399 rajveer 64
    except Exception as ex:
65
        print ex
437 rajveer 66
        raise InventoryServiceException(109, "Item not found")
67
 
576 chandransh 68
def is_active(item_id):
2983 chandransh 69
    t_item_shipping_info = ItemShippingInfo()
576 chandransh 70
    try:
635 rajveer 71
        item = get_item(item_id)
3281 chandransh 72
        t_item_shipping_info.isRisky = item.risky
73
        availability = __get_item_availability(item)
74
        if item.risky and availability <= 0 and item.status == status.ACTIVE:
75
            add_status_change_log(item, status.PAUSED_BY_RISK)
76
            item.status = status.PAUSED_BY_RISK
77
            item.status_description = "This item is currently out of stock"
78
            session.commit()
3924 rajveer 79
            #This will clear cache from tomcat
80
            __clear_homepage_cache()
2983 chandransh 81
        t_item_shipping_info.isActive = (item.status == status.ACTIVE)
3281 chandransh 82
        t_item_shipping_info.quantity = availability
576 chandransh 83
    except InventoryServiceException:
2983 chandransh 84
        print "[ERROR] Unexpected error:", sys.exc_info()[0]
85
    return t_item_shipping_info
86
 
2035 rajveer 87
def get_item_status_description(itemId):
88
    item = get_item(itemId)
89
    return item.status_description
563 chandransh 90
 
94 ashish 91
def get_Warehouse(warehouse_id):
92
    return Warehouse.get_by(id=warehouse_id)
93
 
122 ashish 94
def get_all_warehouses_by_status(status):
95
    if not status:
766 rajveer 96
        warehouses = Warehouse.query.all()
122 ashish 97
    else:
851 chandransh 98
        warehouses = Warehouse.query.filter_by(status=status).all()
99
    return warehouses
122 ashish 100
 
94 ashish 101
def get_all_warehouses_for_item(item_id):
635 rajveer 102
    item = get_item(item_id)
94 ashish 103
    if not item:
122 ashish 104
        raise InventoryServiceException(108, "Some unforeseen error while obtaining item")
105
    return item.get_all_warehouses
94 ashish 106
 
122 ashish 107
def get_all_items_for_warehouse(warehouse_id):
108
    warehouse = get_Warehouse(warehouse_id)
109
    if not warehouse:
110
        raise InventoryServiceException(108, "bad warehouse")
111
    return warehouse.all_items
112
 
94 ashish 113
def add_warehouse(warehouse):
103 ashish 114
    if not warehouse:
122 ashish 115
        raise InventoryServiceException(108, "Bad warehouse")
103 ashish 116
    if get_Warehouse(warehouse.id):
117
        #warehouse is already present.
122 ashish 118
        raise InventoryServiceException(101, "Warehouse already present")
103 ashish 119
 
94 ashish 120
    ds_warehouse = Warehouse()
121
    ds_warehouse.id = warehouse.id
122
    ds_warehouse.location = warehouse.location
122 ashish 123
    ds_warehouse.status = status.ACTIVE
103 ashish 124
    ds_warehouse.addedOn = datetime.datetime.now()
483 rajveer 125
    ds_warehouse.lastCheckedOn = datetime.datetime.now()
126
    ds_warehouse.tinNumber = warehouse.tinNumber
127
    ds_warehouse.pincode = warehouse.pincode
128
    if warehouse.vendorString:
129
        ds_warehouse.vendorString = warehouse.vendorString
94 ashish 130
    session.commit()
103 ashish 131
    return ds_warehouse.id
94 ashish 132
 
122 ashish 133
def update_item(item):
134
    if not item:
135
        raise InventoryServiceException(108, "Bad item in request")
136
 
137
    if not item.id:
609 chandransh 138
        raise InventoryServiceException(101, "Missing id for update")
122 ashish 139
 
2120 ankur.sing 140
    validate_item_prices(item)
2065 ankur.sing 141
 
635 rajveer 142
    ds_item = get_item(item.id)
122 ashish 143
 
144
    if not ds_item:
609 chandransh 145
        raise InventoryServiceException(101, "Item missing in our database")
122 ashish 146
 
963 chandransh 147
    if item.productGroup:
148
        ds_item.product_group = item.productGroup 
149
    if item.brand:
150
        ds_item.brand = item.brand
511 rajveer 151
    if item.modelNumber:
152
        ds_item.model_number = item.modelNumber
2497 ankur.sing 153
    ds_item.color = item.color
154
    ds_item.model_name = item.modelName
155
    ds_item.category = item.category
156
    ds_item.comments = item.comments
511 rajveer 157
 
2497 ankur.sing 158
    ds_item.catalog_item_id = item.catalogItemId
483 rajveer 159
 
2129 ankur.sing 160
    ds_item.mrp = item.mrp
161
    ds_item.sellingPrice = item.sellingPrice
2497 ankur.sing 162
 
2174 ankur.sing 163
    ds_item.weight = item.weight
2129 ankur.sing 164
 
2358 ankur.sing 165
    if ds_item.status != item.itemStatus:
2402 rajveer 166
        add_status_change_log(ds_item, item.itemStatus)
2358 ankur.sing 167
        ds_item.status = item.itemStatus
2035 rajveer 168
    if item.status_description:
169
        ds_item.status_description = item.status_description
122 ashish 170
 
511 rajveer 171
    if item.startDate:
2116 ankur.sing 172
        ds_item.startDate = to_py_date(item.startDate)
2497 ankur.sing 173
    else:
174
        ds_item.startDate = None
511 rajveer 175
    if item.retireDate:
2116 ankur.sing 176
        ds_item.retireDate = to_py_date(item.retireDate)
2497 ankur.sing 177
    else:
178
        ds_item.retireDate = None
511 rajveer 179
 
2497 ankur.sing 180
    ds_item.feature_id = item.featureId
181
    ds_item.feature_description = item.featureDescription
122 ashish 182
 
2129 ankur.sing 183
    ds_item.bestDealText = item.bestDealText
184
    ds_item.bestDealValue = item.bestDealValue
2065 ankur.sing 185
    ds_item.bestSellingRank = item.bestSellingRank
2497 ankur.sing 186
 
2065 ankur.sing 187
    ds_item.defaultForEntity = item.defaultForEntity
2251 ankur.sing 188
    ds_item.risky = item.risky
3359 chandransh 189
 
3459 chandransh 190
    if item.expectedDelay is not None:
3359 chandransh 191
        ds_item.expectedDelay = item.expectedDelay
192
 
193
    if item.preferredWarehouse:
194
        ds_item.preferredWarehouse = item.preferredWarehouse
195
 
2347 ankur.sing 196
    ds_item.updatedOn = datetime.datetime.now()
2065 ankur.sing 197
 
122 ashish 198
    session.commit();
199
    return ds_item.id
94 ashish 200
 
2116 ankur.sing 201
def check_vendor_item_mapping(product_group, brand, model_number, color, vendor_id, vendor_category):
202
    key = product_group.strip().lower() + '|' + brand.strip().lower() + '|' + model_number.strip().lower() + '|' + color.strip().lower()
203
    try:
204
        vim = VendorItemMapping.query.filter_by(vendor_id=vendor_id, item_key=key, vendor_category=vendor_category).one()
205
        return True
206
    except:
207
        return False
208
 
103 ashish 209
def add_item(item):
210
    if not item:
122 ashish 211
        raise InventoryServiceException(108, "Bad item in request")
635 rajveer 212
    if get_item(item.id):
122 ashish 213
        raise InventoryServiceException(101, "Item already exists")
2120 ankur.sing 214
 
215
    validate_item_prices(item)
216
 
103 ashish 217
    ds_item = Item()
963 chandransh 218
    if item.productGroup:
219
        ds_item.product_group = item.productGroup
220
    if item.brand:
221
        ds_item.brand = item.brand
515 rajveer 222
    if item.modelName:
223
        ds_item.model_name = item.modelName
224
    if item.modelNumber:
225
        ds_item.model_number = item.modelNumber
609 chandransh 226
    if item.color:
227
        ds_item.color = item.color
2116 ankur.sing 228
    if item.hotspotCategory:
229
        ds_item.hotspotCategory = item.hotspotCategory
230
        if item.hotspotCategory == 'Handsets':
2403 ankur.sing 231
            ds_item.preferredWarehouse = 1
2116 ankur.sing 232
        else:
2403 ankur.sing 233
            ds_item.preferredWarehouse = 2
2116 ankur.sing 234
 
483 rajveer 235
    if item.category:
236
        ds_item.category = item.category
237
    if item.comments:
238
        ds_item.comments = item.comments
239
 
103 ashish 240
    ds_item.addedOn = datetime.datetime.now()
609 chandransh 241
    ds_item.updatedOn = datetime.datetime.now()
2116 ankur.sing 242
    if item.startDate:
243
        ds_item.startDate = to_py_date(item.startDate)
244
    if item.retireDate:
245
        ds_item.retireDate = to_py_date(item.retireDate)
609 chandransh 246
 
483 rajveer 247
    if item.mrp:
248
        ds_item.mrp = item.mrp
249
    if item.sellingPrice:
250
        ds_item.sellingPrice = item.sellingPrice
122 ashish 251
    if item.weight:
252
        ds_item.weight = item.weight
253
 
254
    if item.featureId:
255
        ds_item.feature_id = item.featureId
256
    if item.featureDescription:
257
        ds_item.feature_description = item.featureDescription
258
 
103 ashish 259
    if item.otherInfo:
260
        for k,v in item.otherInfo.iteritems():
261
            info = ItemInfo()
262
            info.key = k
263
            info.value = v
264
            ds_item.iteminfo.append(info)
2116 ankur.sing 265
 
103 ashish 266
    #check if categories present. If yes, add them to system
122 ashish 267
 
609 chandransh 268
    if item.bestDealValue:
269
        ds_item.bestDealValue = item.bestDealValue
270
    if item.bestDealText:
271
        ds_item.bestDealText = item.bestDealText
2116 ankur.sing 272
    if item.bestSellingRank:
273
        ds_item.bestSellingRank = item.bestSellingRank
274
    ds_item.defaultForEntity = item.defaultForEntity
2251 ankur.sing 275
    ds_item.risky = item.risky
609 chandransh 276
 
3467 chandransh 277
    if item.expectedDelay is not None:
3359 chandransh 278
        ds_item.expectedDelay = item.expectedDelay
3467 chandransh 279
    else:
280
        ds_item.expectedDelay = 0
3359 chandransh 281
 
282
    if item.preferredWarehouse:
283
        ds_item.preferredWarehouse = item.preferredWarehouse
284
 
2116 ankur.sing 285
    # Check if a similar item already exists in our database
286
    similar_item = Item.query.filter_by(product_group=item.productGroup, brand = item.brand, model_number=item.modelNumber, hotspotCategory=item.hotspotCategory).first()
287
    print "[SIMILAR ITEM FOUND:] FOR {0} {1} {2} {3} {4}".format(item.productGroup, item.brand, item.modelNumber, item.hotspotCategory, item.color)
288
 
289
    if similar_item is None or similar_item.catalog_item_id is None:
290
        # If there is no similar item in the database from before,
291
        # use the entity_id_generator
292
        entity_id = EntityIDGenerator.query.first()
293
        ds_item.catalog_item_id = entity_id.id + 1
294
        ds_item.status = status.IN_PROCESS
295
        ds_item.status_description = "This item is in process."
296
        entity_id.id = entity_id.id  + 1
297
    else:
298
        #If a similar item already exists for a product group, brand and model_number, set it as same.
299
        ds_item.catalog_item_id = similar_item.catalog_item_id
300
        ds_item.category = similar_item.category
301
        ds_item.status = similar_item.status
302
        ds_item.status_description = similar_item.status_description
303
 
103 ashish 304
    session.commit();
3325 chandransh 305
    return ds_item.id
306
 
307
def update_inventory_history(warehouse_id, timestamp, availability):
308
    warehouse = get_Warehouse(warehouse_id)
309
    if not warehouse:
310
        raise InventoryServiceException(107, "Warehouse? Where?")
311
    vendor = warehouse.vendor 
312
    time = datetime.datetime.now()
313
    for item_key, quantity in availability.iteritems():
314
        try:
315
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
316
            item = vendor_item_mapping.item
317
        except:
318
            continue  
319
        try:
320
            item_inventory_history = ItemInventoryHistory()
321
            item_inventory_history.warehouse = warehouse
322
            item_inventory_history.item = item
323
            item_inventory_history.timestamp = time
324
            item_inventory_history.availibility = quantity
325
        except:
326
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
327
    session.commit()
103 ashish 328
 
483 rajveer 329
def update_inventory(warehouse_id, timestamp, availability):
330
    warehouse = get_Warehouse(warehouse_id)
331
    if not warehouse:
332
        raise InventoryServiceException(107, "Warehouse? Where?")
333
 
334
    time = datetime.datetime.now()
335
    warehouse.lastCheckedOn = time
336
    warehouse.vendorString = timestamp
1368 chandransh 337
    vendor = warehouse.vendor
2368 ankur.sing 338
    session.commit()
1368 chandransh 339
    for item_key, quantity in availability.iteritems():
483 rajveer 340
        try:
1368 chandransh 341
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
342
            item = vendor_item_mapping.item
494 rajveer 343
        except:
344
            continue  
345
        try:
483 rajveer 346
            current_inventory_snapshot = CurrentInventorySnapshot.get_by(item=item, warehouse=warehouse)
347
            if not current_inventory_snapshot:
348
                current_inventory_snapshot = CurrentInventorySnapshot()
349
                current_inventory_snapshot.item = item
350
                current_inventory_snapshot.warehouse = warehouse
351
                current_inventory_snapshot.availibility = 0
871 chandransh 352
                current_inventory_snapshot.reserved = 0
483 rajveer 353
            # added the difference in the current inventory    
354
            current_inventory_snapshot.availibility = current_inventory_snapshot.availibility + quantity
355
        except:
356
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
2368 ankur.sing 357
        session.commit() 
358
        check_risky_item(item)
483 rajveer 359
 
94 ashish 360
def get_item_inventoy(item_id):
361
 
362
    inventory = Item.get_by(id=item_id).currentInventory
363
    if not inventory:
122 ashish 364
        raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
94 ashish 365
    return inventory
366
 
635 rajveer 367
def get_item_inventory_by_item_id(item_id):
368
    inventory = Item.get_by(id=item_id).currentInventory
379 ashish 369
    if not inventory:
370
        raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
371
    return inventory
372
 
103 ashish 373
 
374
def retire_warehouse(warehouse_id):
375
    if not warehouse_id:
122 ashish 376
        raise InventoryServiceException(101, "Bad warehouse id")
103 ashish 377
    warehouse = get_Warehouse(warehouse_id)
378
    if not warehouse:
122 ashish 379
        raise InventoryServiceException(108, "warehouse id not present")
380
    warehouse.status = status.DELETED;
103 ashish 381
    session.commit()
382
 
383
def retire_item(item_id):
384
    if not item_id:
122 ashish 385
        raise InventoryServiceException(101, "bad item id")
635 rajveer 386
    item = get_item(item_id)
103 ashish 387
    if not item:
122 ashish 388
        raise InventoryServiceException(108, "item id not present")
389
    item.status = status.PHASED_OUT
390
    item.retireDate = datetime.datetime.now()
103 ashish 391
    session.commit()
122 ashish 392
 
393
#need to implement threads based solution here
103 ashish 394
def start_item_on(item_id, timestamp):
395
    if not item_id:
122 ashish 396
        raise InventoryServiceException(101, "bad item id")
635 rajveer 397
    item = get_item(item_id)
103 ashish 398
    if not item:
122 ashish 399
        raise InventoryServiceException(108, "item id not present")
103 ashish 400
 
122 ashish 401
    item.status = status.ACTIVE
402
    item.startDate = datetime.datetime.fromtimestamp(to_py_date(timestamp))
403
    add_status_change_log(item, status.ACTIVE)
103 ashish 404
    session.commit()
405
 
122 ashish 406
#need to implement threads here
103 ashish 407
def retire_item_on(item_id, timestamp):
408
    if not item_id:
122 ashish 409
        raise InventoryServiceException(101, "bad item id")
635 rajveer 410
    item = get_item(item_id)
103 ashish 411
    if not item:
122 ashish 412
        raise InventoryServiceException(108, "item id not present")
103 ashish 413
 
122 ashish 414
    item.status = status.PHASED_OUT
415
    item.retireDate = datetime.datetime.fromtimestamp(to_py_date(timestamp))
416
    add_status_change_log(item, status.PHASED_OUT)
103 ashish 417
    session.commit()
418
 
419
def add_status_change_log(item, new_status):
420
    item_change_log = ItemChangeLog()
421
    item_change_log.new_status = new_status
422
    item_change_log.old_status = item.status
423
    item_change_log.timestamp = datetime.datetime.now()
424
    item_change_log.item = item
425
    session.commit()
426
 
427
def change_item_status(item_id, new_status):
428
    if not item_id:
122 ashish 429
        raise InventoryServiceException(101, "bad item id")
635 rajveer 430
    item = get_item(item_id)
103 ashish 431
    if not item:
122 ashish 432
        raise InventoryServiceException(108, "item id not present")
2116 ankur.sing 433
    add_status_change_log(item, new_status)
122 ashish 434
    item.status = new_status
2251 ankur.sing 435
    if item.status == status.PHASED_OUT:
436
        item.status_description = "This item has been phased out"
437
    elif item.status == status.DELETED:
438
        item.status_description = "This item has been deleted"
3924 rajveer 439
    elif item.status == status.PAUSED:
440
        item.status_description = "This item is currently out of stock"      
441
    elif item.status == status.PAUSED_BY_RISK:
442
        item.status_description = "This item is currently out of stock"
443
        #This will clear cache from tomcat
444
        __clear_homepage_cache()  
2251 ankur.sing 445
    elif item.status == status.ACTIVE:
446
        item.status_description = "This item is active"
447
    elif item.status == status.IN_PROCESS:
448
        item.status_description = "This item is in process"
449
    elif item.status == status.CONTENT_COMPLETE:
450
        item.status_description = "This item is in process"
103 ashish 451
    session.commit()
452
 
453
def get_item_availability_for_warehouse(warehouse_id, item_id):
454
    if not warehouse_id:
122 ashish 455
        raise InventoryServiceException(101, "bad warehouse_id")
103 ashish 456
    if not item_id:
122 ashish 457
        raise InventoryServiceException(101, "bad item_id")
103 ashish 458
 
459
    warehouse = get_Warehouse(warehouse_id)
460
    if not warehouse:
122 ashish 461
        raise InventoryServiceException(108, "warehouse does not exist")
635 rajveer 462
    item = get_item(item_id)
504 rajveer 463
 
103 ashish 464
    if not item:
766 rajveer 465
        raise InventoryServiceException(108, "item does not exist")
122 ashish 466
 
494 rajveer 467
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id)
504 rajveer 468
    query = query.filter_by(item_id = item.id)
494 rajveer 469
    try:
470
        current_inventory_snapshot = query.one()
871 chandransh 471
        return current_inventory_snapshot.availibility - current_inventory_snapshot.reserved
494 rajveer 472
    except:
473
        return 0
474
    """
475
    current_inventory_snapshot = CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id == warehouse_id, CurrentInventorySnapshot.item_id == item_id).one()
103 ashish 476
    if not current_inventory_snapshot:
477
        return 0
478
    else:
479
        return current_inventory_snapshot.availibility
494 rajveer 480
    """
643 chandransh 481
 
2368 ankur.sing 482
def check_risky_item(item):
2251 ankur.sing 483
    if not item.risky:
484
        return
2983 chandransh 485
    availability = __get_item_availability(item)
486
    if availability <= 0:
2251 ankur.sing 487
        if item.status == status.ACTIVE:
2984 rajveer 488
            change_item_status(item.id, status.PAUSED_BY_RISK)
2251 ankur.sing 489
    else:
2984 rajveer 490
        if item.status == status.PAUSED_BY_RISK:
2251 ankur.sing 491
            change_item_status(item.id, status.ACTIVE)
2368 ankur.sing 492
    session.commit()
2251 ankur.sing 493
 
2983 chandransh 494
def __get_item_availability(item):
495
    all_inventory = CurrentInventorySnapshot.query.filter_by(item = item).all()
496
    availability = 0
497
    reserved = 0
498
    for currInv in all_inventory:
499
        availability = availability + currInv.availibility
500
        reserved = reserved + currInv.reserved
501
    return availability - reserved
502
 
871 chandransh 503
def reserve_item_in_warehouse(item_id, warehouse_id, quantity):    
504
    if not warehouse_id:
505
        raise InventoryServiceException(101, "bad warehouse_id")
2251 ankur.sing 506
    item = get_item(item_id)
507
    if not item:
871 chandransh 508
        raise InventoryServiceException(101, "bad item_id")
509
 
510
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
511
    try:
512
        current_inventory_snapshot = query.one()
513
    except:
4103 chandransh 514
        current_inventory_snapshot = CurrentInventorySnapshot()
515
        current_inventory_snapshot.warehouse_id = warehouse_id
516
        current_inventory_snapshot.item_id = item_id
517
        current_inventory_snapshot.availibility = 0
518
        current_inventory_snapshot.reserved = 0
519
 
520
    current_inventory_snapshot.reserved = current_inventory_snapshot.reserved + quantity
521
    session.commit()
522
    check_risky_item(item)
523
    return True
871 chandransh 524
 
525
def reduce_reservation_count(item_id, warehouse_id, quantity):
526
    if not warehouse_id:
527
        raise InventoryServiceException(101, "bad warehouse_id")
2251 ankur.sing 528
    item = get_item(item_id)
529
    if not item:
871 chandransh 530
        raise InventoryServiceException(101, "bad item_id")
531
 
532
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
533
    try:
534
        current_inventory_snapshot = query.one()
535
        current_inventory_snapshot.reserved = current_inventory_snapshot.reserved - quantity
536
        session.commit()
2368 ankur.sing 537
        check_risky_item(item)
871 chandransh 538
        return True
539
    except:
540
        print "Unexpected error:", sys.exc_info()[0]
541
        return False
542
 
2075 rajveer 543
def mark_item_as_content_complete(entity_id, category, brand, modelName, modelNumber):
2828 rajveer 544
    '''
545
    Get all the items for this entityID and update category, brand, modelName and modelNumber for all.
546
    Update Status for only IN_PROCESS items to CONTENT_COMPLETE
547
    '''
723 chandransh 548
    content_complete_status = status.CONTENT_COMPLETE
2828 rajveer 549
    items = Item.query.filter_by(catalog_item_id=entity_id).all()
723 chandransh 550
    current_timestamp = datetime.datetime.now()
551
    for item in items:
2828 rajveer 552
        if item.status == status.IN_PROCESS:
553
            item.status = content_complete_status
554
            item_change_log = ItemChangeLog()
555
            item_change_log.old_status = item.status
556
            item_change_log.new_status = content_complete_status
557
            item_change_log.timestamp = current_timestamp
558
            item_change_log.item = item
723 chandransh 559
 
2075 rajveer 560
        item.category = category
561
        item.brand = brand
2081 rajveer 562
        item.model_name = modelName
563
        item.model_number = modelNumber
723 chandransh 564
        item.updatedOn = current_timestamp
565
    session.commit()
566
    return True
1294 chandransh 567
 
643 chandransh 568
def get_item_availability_for_location(warehouse_loc, item_id):
3355 chandransh 569
    """
570
    Determines the warehouse that should be used to fulfil an order for the given item.
571
    It first checks all the warehouses which are in the logistics location given by the
572
    warehouse_loc parameter. If none of the warehouses there have any inventory, then the
573
    preferred warehouse for the item is used.
574
 
575
    Returns an ordered list of size 4 with following elements in the given order:
576
    1. Logistics location of the warehouse which was finally picked up to ship the order.
577
    2. Id of the warehouse which was finally picked up.
578
    3. Inventory size in the selected warehouse.
579
    4. Expected delay added by the category manager.
580
 
581
    Parameters:
582
     - warehouse_loc
583
     - item_id
584
    """
643 chandransh 585
    if warehouse_loc is None:
586
        raise InventoryServiceException(101, "Bad Warehouse Location")
587
    if not item_id:
1416 chandransh 588
        raise InventoryServiceException(101, "Bad Item id")
643 chandransh 589
 
1416 chandransh 590
    item = Item.get_by(id=item_id)
3355 chandransh 591
 
592
    #First try all warehouses in the suggested location.
643 chandransh 593
    warehouses = Warehouse.query.filter_by(logisticsLocation=warehouse_loc).all()
594
    warehouse_ids = [warehouse.id for warehouse in warehouses]
595
    warehouse_retid = -1
3503 chandransh 596
    max_availability = 0
597
    total_availability = 0
643 chandransh 598
    for warehouse_id in warehouse_ids:
785 rajveer 599
        try:
871 chandransh 600
            current_inventory_snapshot = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id).one()
601
            availability = current_inventory_snapshot.availibility - current_inventory_snapshot.reserved
785 rajveer 602
        except:
603
            availability = 0    
3503 chandransh 604
        if availability > max_availability:
643 chandransh 605
            warehouse_retid = warehouse_id
3503 chandransh 606
            max_availability = availability
607
        total_availability = total_availability + availability
2341 chandransh 608
 
3355 chandransh 609
    #If no warehouse could be found, use the preferred warehouse for this item
643 chandransh 610
    if warehouse_retid == -1:
759 chandransh 611
        # This is the case when all warehouses have exhausted their
612
        # inventory of this item or no warehouse is available in this
613
        # location.
1416 chandransh 614
        warehouse_retid = int(item.preferredWarehouse)
2344 chandransh 615
        warehouse = Warehouse.get_by(id=warehouse_retid)
2341 chandransh 616
        try:
617
            current_inventory_snapshot = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_retid, item_id = item_id).one()
3503 chandransh 618
            max_availability = current_inventory_snapshot.availibility - current_inventory_snapshot.reserved
2341 chandransh 619
        except:
3503 chandransh 620
            max_availability = 0
621
        total_availability = max_availability
643 chandransh 622
 
3503 chandransh 623
    return [warehouse.logisticsLocation, warehouse_retid, total_availability, item.expectedDelay]
2341 chandransh 624
 
122 ashish 625
def get_warehouses_for_item(item_id):
643 chandransh 626
 
122 ashish 627
    if not item_id:
628
        raise InventoryServiceException(101, "bad item_id")
635 rajveer 629
    item = get_item(item_id)
122 ashish 630
 
631
    if not item:
632
        raise InventoryServiceException(101, "bad item")
633
 
483 rajveer 634
    warehouses = item.currentInventory.warehouse
501 rajveer 635
    return warehouses
636
 
2404 chandransh 637
def get_child_categories(category):
638
    cm = CategoryManager()
2621 varun.gupt 639
    cat = cm.getCategory(category)
640
    return cat.children_category_ids if cat else None
2404 chandransh 641
 
626 chandransh 642
def get_best_sellers(start_index, stop_index, category=-1):
2404 chandransh 643
    '''
644
    Returns the Best Sellers between the start and the stop index in the given category
645
    '''
1926 rajveer 646
    query = get_best_sellers_query(category, None)
1098 chandransh 647
    best_sellers = query.all()[start_index:stop_index]
621 chandransh 648
    return get_thrift_item_list(best_sellers)
649
 
2093 chandransh 650
def get_best_sellers_count(category=-1):
2404 chandransh 651
    '''
652
    Returns the number of best sellers in the given category
653
    '''
1926 rajveer 654
    count = get_best_sellers_query(category, None).count()
1120 rajveer 655
    if count is None:
656
        count = 0
766 rajveer 657
    return count
621 chandransh 658
 
1926 rajveer 659
def get_best_sellers_catalog_ids(start_index, stop_index, brand, category=-1):
2404 chandransh 660
    '''
661
    Returns the Best sellers for the given brand and category between the start and the stop index.
662
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
663
    '''
1926 rajveer 664
    query = get_best_sellers_query(category, brand)
1098 chandransh 665
    best_sellers = query.all()[start_index:stop_index]
621 chandransh 666
    return [item.catalog_item_id for item in best_sellers]
1970 rajveer 667
 
1926 rajveer 668
def get_best_sellers_query(category, brand):
2404 chandransh 669
    '''
670
    Returns the query to be used for getting Best Sellers.
671
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
672
    '''
1098 chandransh 673
    query = Item.query.filter_by(status=status.ACTIVE).filter(Item.bestSellingRank != None)
626 chandransh 674
    if category != -1:
1970 rajveer 675
        all_categories = [category]
676
        child_categories = get_child_categories(category)
677
        if child_categories is not None:
678
            all_categories = all_categories + child_categories 
679
        query = query.filter(Item.category.in_(all_categories))
1926 rajveer 680
    if brand is not None:
681
        query = query.filter_by(brand=brand)
1098 chandransh 682
    query = query.order_by(asc(Item.bestSellingRank))
621 chandransh 683
    return query
609 chandransh 684
 
1098 chandransh 685
def get_best_deals(category=-1):
2404 chandransh 686
    '''
687
    Returns the Best deals in the given category. Ignores the category if it's passed as -1.
688
    '''
689
    query = get_best_deals_query(Item, category, None)
1098 chandransh 690
    items = query.all()
609 chandransh 691
    return get_thrift_item_list(items)
692
 
1098 chandransh 693
def get_best_deals_count(category=-1):
2404 chandransh 694
    '''
695
    Returns the count of best deals in the given category.
696
    Ignores the category if it's -1.
697
    '''
698
    count = get_best_deals_counting_query(func.count(distinct(Item.catalog_item_id)), category, None).scalar()
1120 rajveer 699
    if count is None:
700
        count = 0
766 rajveer 701
    return count
501 rajveer 702
 
1926 rajveer 703
def get_best_deals_catalog_ids(start_index, stop_index, brand, category=-1):
2404 chandransh 704
    '''
705
    Returns the catalog_item_ids of best deal items for the given brand and category.
706
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
707
    '''
708
    query = get_best_deals_query(Item, category, brand)
1098 chandransh 709
    best_deal_items = query.all()[start_index:stop_index]
710
    return [item.catalog_item_id for item in best_deal_items]
711
 
2404 chandransh 712
def get_best_deals_counting_query(obj, category, brand):
713
    '''
714
    Returns the query to be used to select the best deals in the given brand and category.
715
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
716
    '''
717
    query = session.query(obj).filter_by(status=status.ACTIVE).filter(Item.bestDealValue != None)
626 chandransh 718
    if category != -1:
1970 rajveer 719
        all_categories = [category]
720
        child_categories = get_child_categories(category)
721
        if child_categories is not None:
722
            all_categories = all_categories + child_categories 
723
        query = query.filter(Item.category.in_(all_categories))
1926 rajveer 724
    if brand is not None:
725
        query = query.filter_by(brand=brand)
2404 chandransh 726
    return query
727
 
728
def get_best_deals_query(obj, category, brand):
729
    '''
730
    Returns the query to be used to get the best deals in the given category and brand.
731
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
732
    '''
733
    query = get_best_deals_counting_query(obj, category, brand)
1098 chandransh 734
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.bestDealValue))
735
    return query
609 chandransh 736
 
1098 chandransh 737
def get_latest_arrivals(limit, category=-1):
2404 chandransh 738
    '''
739
    Returns up to limit number of Latest Arrivals in the given category.
740
    '''
2975 chandransh 741
    categories = []
742
    if category != -1:
743
        categories = [category]
744
    query = get_latest_arrivals_query(Item, categories, None)
1098 chandransh 745
    items = query.all()[0:limit]
609 chandransh 746
    return get_thrift_item_list(items)
598 chandransh 747
 
1098 chandransh 748
def get_latest_arrivals_count(limit, category=-1):
2404 chandransh 749
    '''
750
    Returns the number of latest arrivals which will be displayed on the website.
3016 chandransh 751
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 752
    '''
2975 chandransh 753
    categories = []
754
    if category != -1:
755
        categories = [category]
756
    count = get_latest_arrivals_counting_query(func.count(distinct(Item.catalog_item_id)), categories, None).scalar()
1120 rajveer 757
    if count is None:
758
        count = 0
759
    count = min(count, limit)
766 rajveer 760
    return count
602 chandransh 761
 
2975 chandransh 762
def get_latest_arrivals_catalog_ids(start_index, stop_index, brand, categories=[]):
2404 chandransh 763
    '''
764
    Returns the catalog_item_ids of the latest arrivals between the start and the stop index
3016 chandransh 765
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 766
    '''
2975 chandransh 767
    query = get_latest_arrivals_query(Item, categories, brand)
1098 chandransh 768
    latest_arrivals = query.all()[start_index:stop_index]
769
    return [item.catalog_item_id for item in latest_arrivals]
770
 
2975 chandransh 771
def get_latest_arrivals_counting_query(obj, categories, brand):
2404 chandransh 772
    '''
773
    Returns the query to be used to count Latest arrivals.
3016 chandransh 774
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 775
    '''
776
    query = session.query(obj).filter_by(status=status.ACTIVE)
2975 chandransh 777
 
778
    all_categories = []
779
    for category in categories:
780
        all_categories.append(category)
1970 rajveer 781
        child_categories = get_child_categories(category)
2975 chandransh 782
        if child_categories:
783
            all_categories = all_categories + child_categories
784
    if all_categories: 
1970 rajveer 785
        query = query.filter(Item.category.in_(all_categories))
2975 chandransh 786
 
1926 rajveer 787
    if brand is not None:
788
        query = query.filter_by(brand=brand)
2404 chandransh 789
    return query
790
 
2975 chandransh 791
def get_latest_arrivals_query(obj, categories, brand):
2404 chandransh 792
    '''
793
    Returns the query to be used to retrieve Latest Arrivals.
794
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
795
    '''
2975 chandransh 796
    query = get_latest_arrivals_counting_query(obj, categories, brand)
1098 chandransh 797
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.startDate))
798
    return query
609 chandransh 799
 
800
def get_thrift_item_list(items):
1098 chandransh 801
    return [to_t_item(item) for item in items if item != None]
635 rajveer 802
 
1155 rajveer 803
def generate_new_entity_id():
804
    generator =  EntityIDGenerator.query.one()
805
    id = generator.id + 1
806
    generator.id = id
807
    session.commit()
808
    return id
809
 
635 rajveer 810
def put_category_object(object):
811
    category = Category.get_by(id=1)
812
    if category is None:
813
        category = Category()
814
    category.object = object    
815
    session.commit()
816
    return True
817
 
818
def get_category_object():
766 rajveer 819
    object = Category.get_by(id=1).object
820
    return object
821
 
4283 anupam.sin 822
def get_item_pricing(item_id, vendorId):
1341 chandransh 823
    item = Item.query.filter_by(id=item_id).first()
824
    if item is None:
825
        raise InventoryServiceException(101, "Bad Item")
4307 anupam.sin 826
    '''
827
    if vendor id is -1 then we calculate an average transfer price to be populated
828
    at the time of order creation. This will be later updated with actual transfer price
829
    at the time of billing.
830
    '''
831
    if(vendorId == -1):
832
        try:
833
            item_pricings = VendorItemPricing.query.filter_by(item=item).all()
4315 anupam.sin 834
            if item_pricings:
4307 anupam.sin 835
                for item_pricing in item_pricings:
4315 anupam.sin 836
                    total =+ item_pricing.transfer_price
837
                avg = total / len(item_pricings)
838
                item_pricing.transfer_price = avg
839
                return item_pricing
4307 anupam.sin 840
        except:
841
            raise InventoryServiceException(101, "Item pricing not found ")
4283 anupam.sin 842
    vendor = Vendor.get_by(id=vendorId)    
1341 chandransh 843
    try:
844
        item_pricing = VendorItemPricing.query.filter_by(vendor=vendor, item=item).one()
1347 chandransh 845
        return item_pricing
3244 chandransh 846
    except MultipleResultsFound:
1341 chandransh 847
        raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
3244 chandransh 848
    except NoResultFound:
1341 chandransh 849
        raise InventoryServiceException(111, "Missing pricing information for Vendor: " + vendor.name + " and Item: " + str(item_id))
850
 
1970 rajveer 851
def add_category(t_category):
852
    category = Category.get_by(id=t_category.id)
853
    if category is None:
854
        category = Category()
855
    category.id = t_category.id 
856
    category.label = t_category.label
857
    category.description = t_category.description
858
    category.parent_category_id = t_category.parent_category_id 
859
    session.commit()
860
    return True
861
 
862
def get_category(id):
863
    return Category.query.filter_by(id=id).first()
864
 
865
def get_all_categories():
866
    return Category.query.all()
867
 
1991 ankur.sing 868
 
869
def get_all_item_pricing(item_id):
870
    item = Item.query.filter_by(id=item_id).first()
871
    if item is None:
872
        raise InventoryServiceException(101, "Bad Item")
873
    item_pricing = VendorItemPricing.query.filter_by(item=item).all()
874
    return item_pricing
875
 
2116 ankur.sing 876
def get_item_mappings(item_id):
877
    item = Item.query.filter_by(id=item_id).first()
878
    if item is None:
879
        raise InventoryServiceException(101, "Bad Item")
880
    item_mappings = VendorItemMapping.query.filter_by(item=item).all()
881
    return item_mappings
882
 
883
def add_vendor_pricing(vendorItemPricing):
1991 ankur.sing 884
    if not vendorItemPricing:
885
        raise InventoryServiceException(108, "Bad vendorItemPricing in request")
886
    vendorId = vendorItemPricing.vendorId
887
    itemId = vendorItemPricing.itemId
888
 
889
    try:
890
        vendor = Vendor.query.filter_by(id=vendorId).one()
891
    except:
892
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
893
 
894
    try:
895
        item = Item.query.filter_by(id=itemId).one()
896
    except:
897
        raise InventoryServiceException(101, "Item not found for vendorId " + str(itemId))
898
 
2120 ankur.sing 899
    validate_vendor_prices(to_t_item(item), vendorItemPricing)
2065 ankur.sing 900
 
1991 ankur.sing 901
    try:
902
        ds_vendorItemPricing = VendorItemPricing.query.filter(and_(VendorItemPricing.vendor==vendor, VendorItemPricing.item==item)).one()
903
    except:
2116 ankur.sing 904
        ds_vendorItemPricing = VendorItemPricing()
905
        ds_vendorItemPricing.vendor = vendor
906
        ds_vendorItemPricing.item = item
1991 ankur.sing 907
 
908
    if vendorItemPricing.mop:
909
        ds_vendorItemPricing.mop = vendorItemPricing.mop
910
    if vendorItemPricing.dealerPrice:
911
        ds_vendorItemPricing.dealerPrice = vendorItemPricing.dealerPrice
912
    if vendorItemPricing.transferPrice:
2065 ankur.sing 913
        ds_vendorItemPricing.transfer_price = vendorItemPricing.transferPrice
1991 ankur.sing 914
 
915
    session.commit()
916
    return
917
 
2358 ankur.sing 918
def add_vendor_item_mapping(key, vendorItemMapping):
2116 ankur.sing 919
    if not vendorItemMapping:
920
        raise InventoryServiceException(108, "Bad vendorItemMapping in request")
921
    vendorId = vendorItemMapping.vendorId
922
    itemId = vendorItemMapping.itemId
923
 
924
    try:
925
        vendor = Vendor.query.filter_by(id=vendorId).one()
926
    except:
927
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
928
 
929
    try:
930
        item = Item.query.filter_by(id=itemId).one()
931
    except:
932
        raise InventoryServiceException(101, "Item not found for vendorId " + str(itemId))
933
 
934
    try:
2358 ankur.sing 935
        ds_vendorItemMapping = VendorItemMapping.query.filter(and_(VendorItemMapping.vendor==vendor, VendorItemMapping.item==item, VendorItemMapping.item_key==key)).one()
2116 ankur.sing 936
    except:
937
        ds_vendorItemMapping = VendorItemMapping()
938
        ds_vendorItemMapping.vendor = vendor
939
        ds_vendorItemMapping.item = item
2497 ankur.sing 940
    ds_vendorItemMapping.vendor_category = vendorItemMapping.vendorCategory
2116 ankur.sing 941
    ds_vendorItemMapping.item_key = vendorItemMapping.itemKey
942
 
943
    session.commit()
944
    return
945
 
2120 ankur.sing 946
def validate_item_prices(item):
2129 ankur.sing 947
    if item.mrp == None or item.sellingPrice == None or item.mrp == "" or item.sellingPrice == "":
948
        return
949
    if item.mrp < item.sellingPrice:
2120 ankur.sing 950
        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))
951
        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 952
    return
2120 ankur.sing 953
 
954
def validate_vendor_prices(item, vendorPrices):
2129 ankur.sing 955
    if item.mrp != None and item.mrp != "" and vendorPrices.mop != "" and item.mrp <  vendorPrices.mop:
2120 ankur.sing 956
        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))
957
        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)))
958
    if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
959
        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))
960
        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)))
961
    return
2065 ankur.sing 962
 
963
def get_all_vendors():
964
    return Vendor.query.all()
965
 
2116 ankur.sing 966
def check_similar_item(product_group, brand, model_number, color):
2129 ankur.sing 967
    query = Item.query
2428 ankur.sing 968
    query = query.filter_by(product_group=product_group)
969
    query = query.filter_by(brand=brand)
970
    query = query.filter_by(model_number=model_number)
2129 ankur.sing 971
    if color:
972
        query = query.filter_by(color=color)
973
    item = query.first()
2116 ankur.sing 974
    if item is None:
975
        return 0
976
    else:
977
        return item.id
2286 ankur.sing 978
 
979
def change_risky_flag(item_id, risky):
980
    item = get_item(item_id)
981
    if not item:
982
        raise InventoryServiceException(101, "Item missing in our database")
983
    try:
984
        log_risky_flag(item_id, risky)
985
    except:
986
        print "Not able to log risky flag change"
987
    item.risky = risky
4295 varun.gupt 988
    if not risky and item.status == status.PAUSED_BY_RISK:
2368 ankur.sing 989
        change_item_status(item.id, status.ACTIVE)
2286 ankur.sing 990
    session.commit()
991
 
2358 ankur.sing 992
def get_items_by_vendor_category(vendor_category):
993
    if not vendor_category:
994
        raise InventoryServiceException(101, "Invalid vendor category in request")
995
    query = Item.query.filter(and_(Item.hotspotCategory==vendor_category, Item.status != status.PHASED_OUT))
996
    items = query.all()
997
    return items
2116 ankur.sing 998
 
2358 ankur.sing 999
def get_risky_items():
1000
    items = Item.query.filter_by(risky=True).all()
1001
    return items
3008 rajveer 1002
 
2809 rajveer 1003
def get_similar_items_catalog_ids(start_index, stop_index, itemId):
3008 rajveer 1004
    query = SimilarItems.query.filter_by(item_id=itemId).limit(stop_index-start_index)
1005
    similar_items = query.all()
3289 rajveer 1006
    return_list = []
1007
    for similar_item in similar_items:
1008
        isActive = False
1009
        try:
1010
            all_items = Item.query.filter_by(catalog_item_id=similar_item.catalog_item_id).all()
1011
        except:
1012
            continue
1013
        for item in all_items:
1014
            isActive = isActive or item.status == status.ACTIVE
1015
        if isActive:
1016
            return_list.append(similar_item.catalog_item_id)
1017
    return return_list
2809 rajveer 1018
 
3079 rajveer 1019
def add_product_notification(itemId, email):
1020
    try:
3470 rajveer 1021
        try:
1022
            product_notification = ProductNotification.query.filter_by(item_id=itemId, email=email).one()
1023
        except:
1024
            product_notification = ProductNotification()
1025
            product_notification.email = email
1026
            product_notification.item_id = itemId
3079 rajveer 1027
        product_notification.addedOn = datetime.datetime.now()
1028
        session.commit()
1029
        return True
1030
    except:
1031
        return False
3086 rajveer 1032
 
1033
 
1034
def send_product_notifications():
1035
    product_notifications = ProductNotification.query.all()
1036
    for product_notification in product_notifications:
1037
        item = product_notification.item
1038
        availability = __get_item_availability(item)
3309 rajveer 1039
        if availability > 0 and item.status == status.ACTIVE:
3086 rajveer 1040
            __enque_product_notification_email(product_notification.email, __get_product_name(item) , product_notification.addedOn, __get_product_url(item), item.id)
1041
            product_notification.delete()
1042
    session.commit()
1043
    return True
1044
 
1045
def __get_product_name(item):
1046
    product_name = item.brand + " " + item.model_name + " " + item.model_number
1047
    color = item.color
1048
    if color is not None and color != 'NA':
1049
        product_name = product_name + " (" + color + ")"
3201 rajveer 1050
    product_name = product_name.replace("  "," ")
3086 rajveer 1051
    return product_name
1052
 
1053
 
1054
def __get_product_url(item):
1055
    product_url = "http://www.saholic.com/mobile-phones/" + item.brand + "-" + item.model_name + "-" + item.model_number + "-" + str(item.catalog_item_id)
1056
    product_url = product_url.replace("--","-")
1057
    product_url = product_url.replace(" ","")
1058
    return product_url
1059
 
3348 varun.gupt 1060
def get_all_brands_by_category(category_id):
1061
    catm = CategoryManager()
1062
    child_categories = catm.getCategory(category_id).children_category_ids
1063
    brands = session.query(distinct(Item.brand)).filter(Item.category.in_(child_categories)).all()
1064
 
1065
    return [brand[0] for brand in brands]
3086 rajveer 1066
 
1067
def __enque_product_notification_email(email, product, date, url, itemId):
1068
 
1069
    html = """
1070
        <html>
1071
        <body>
1072
        <div>
1073
        <p>
1074
            Hi,<br /><br />
1075
            The product requested by you on $date is now available on saholic.com.
1076
        </p>
1077
 
1078
        <p>    
1079
        <strong>Product: $product </strong>
1080
        </p>
1081
 
1082
        <p>
1083
        Click the link below to visit the product: 
1084
        <br/>
1085
        $url
1086
        </p>
1087
        <p>
1088
        Regards,<br/>
1089
        Saholic Customer Support Team<br/>
1090
        www.saholic.com<br/>
1091
        Email: help@saholic.com<br/>
1092
        </p>
1093
        </div>
1094
        </body>
1095
        </html>
1096
        """
1097
 
1098
    html = Template(html).substitute(dict(product=product,date=date,url=url))
3079 rajveer 1099
 
3086 rajveer 1100
    try:
1101
        helper_client = HelperClient().get_client()
1102
        helper_client.saveUserEmailForSending(email, "", "Product requested by you is available now.", html, str(itemId), "ProductNotification")
1103
    except Exception as e:
1104
        print e
1105
 
3557 rajveer 1106
def get_all_sources():
1107
    sources = Source.query.all()
1108
    return [to_t_source(source) for source in sources]
3086 rajveer 1109
 
3557 rajveer 1110
def get_item_pricing_by_source(itemId, sourceId):
1111
    item = Item.query.filter_by(id=itemId).first()
1112
    if item is None:
1113
        raise InventoryServiceException(101, "Bad Item")
1114
 
1115
    source = Source.query.filter_by(id=sourceId).first()
1116
    if source is None:
1117
        raise InventoryServiceException(101, "Source not found for sourceId " + str(sourceId))
1118
 
1119
    item_pricing = SourceItemPricing.query.filter_by(source=source, item=item).first()
1120
    if item_pricing is None:
1121
        raise InventoryServiceException(101, "Pricing information not found for sourceId " + str(sourceId))
1122
    return item_pricing
1123
 
1124
def add_source_item_pricing(sourceItemPricing):
1125
    if not sourceItemPricing:
1126
        raise InventoryServiceException(108, "Bad sourceItemPricing in request")
1127
 
1128
    if not sourceItemPricing.sellingPrice:
1129
        raise InventoryServiceException(101, "Selling Price is not defined for sourceId " + str(sourceId))
1130
 
1131
    sourceId = sourceItemPricing.sourceId
1132
    itemId = sourceItemPricing.itemId
1133
 
1134
    item = Item.query.filter_by(id=itemId).first()
1135
    if item is None:
1136
        raise InventoryServiceException(101, "Bad Item")
1137
 
1138
    source = Source.query.filter_by(id=sourceId).first()
1139
    if source is None:
1140
        raise InventoryServiceException(101, "Source not found for sourceId " + str(sourceId))
1141
 
3564 rajveer 1142
    ds_sourceItemPricing = SourceItemPricing.get_by(source=source, item=item)
3557 rajveer 1143
    if ds_sourceItemPricing is None:
1144
        ds_sourceItemPricing = SourceItemPricing()
1145
        ds_sourceItemPricing.source = source
1146
        ds_sourceItemPricing.item = item
1147
 
1148
    if sourceItemPricing.mrp:
1149
        ds_sourceItemPricing.mrp = sourceItemPricing.mrp
1150
    ds_sourceItemPricing.sellingPrice = sourceItemPricing.sellingPrice
1151
 
1152
    session.commit()
1153
    return
1154
 
1155
def get_all_source_pricing(itemId):
1156
    item = Item.query.filter_by(id=itemId).first()
1157
    if item is None:
1158
        raise InventoryServiceException(101, "Bad Item")
1159
    source_pricing = SourceItemPricing.query.filter_by(item=item).all()
1160
    return source_pricing
1161
 
1162
 
1163
def get_item_for_source(item_id, sourceId):
1164
    item = get_item(item_id)
1165
    if sourceId == -1:
1166
        return item
1167
    try:
1168
        sip = get_item_pricing_by_source(item_id, sourceId)
1169
        item.sellingPrice = sip.sellingPrice
1170
        if sip.mrp:
1171
            item.mrp = sip.mrp
1172
    except:
1173
        print "No source pricing"
1174
    return item
1175
 
3872 chandransh 1176
def search_items(search_terms, offset, limit):
1177
    query = Item.query
1178
 
1179
    query_clause = []
1180
 
1181
    search_terms = ['%' + search_term + '%' for search_term in search_terms]
1182
 
1183
    for search_term in search_terms:
1184
        query_clause.append(Item.brand.like(search_term))
1185
        query_clause.append(Item.model_number.like(search_term))
1186
        query_clause.append(Item.model_name.like(search_term))
1187
 
1188
    query = query.filter(or_(*query_clause))
1189
 
1190
    query = query.order_by(Item.product_group, Item.brand, Item.model_number, Item.model_name).offset(offset)
1191
    if limit:
1192
        query = query.limit(limit)
1193
    items = query.all()
1194
    return items
1195
 
1196
def get_search_result_count(search_terms):
1197
    query = Item.query
1198
 
1199
    query_clause = []
1200
 
1201
    search_terms = ['%' + search_term + '%' for search_term in search_terms]
1202
 
1203
    for search_term in search_terms:
1204
        query_clause.append(Item.brand.like(search_term))
1205
        query_clause.append(Item.model_number.like(search_term))
1206
        query_clause.append(Item.model_name.like(search_term))
1207
 
1208
    query = query.filter(or_(*query_clause))
1209
 
1210
    return query.count()
1211
 
3924 rajveer 1212
def __clear_homepage_cache():
1213
    try:
1214
        # create a password manager
1215
        password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
1216
        # Add the username and password.
1217
        configclient = ConfigClient()
4310 rajveer 1218
        ips = configclient.get_property("production_servers_private_ips");
3924 rajveer 1219
        ips = ips.split(" ")
1220
 
1221
        for ip in ips:
4310 rajveer 1222
            try:
1223
                top_level_url = "http://" + ip + ":8080/"
1224
                password_mgr.add_password(None, top_level_url, "saholic", "shop2020")
1225
                handler = urllib2.HTTPBasicAuthHandler(password_mgr)
3924 rajveer 1226
 
4310 rajveer 1227
                opener = urllib2.build_opener(handler)
3924 rajveer 1228
 
4310 rajveer 1229
                # use the opener to fetch a URL
1230
                res = opener.open(top_level_url + "cache-admin/HomePageSnippets?_method=delete")
1231
                print "Successfully cleared home page cache" + res.read()
1232
            except:
1233
                print "Unable to clear home page cache" + res.read()
3924 rajveer 1234
    except:
1235
        print "Unable to clear cache, still should continue with other operations"
4024 chandransh 1236
 
4062 chandransh 1237
def get_pending_orders_inventory(vendor_id=1):
4024 chandransh 1238
    """
1239
    Returns a list of inventory stock for items for which there are pending orders.
1240
    """
4062 chandransh 1241
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter_by(vendor_id=vendor_id).all()]
4064 chandransh 1242
    pending_items_inventory = []
1243
    if warehouse_ids:
1244
        pending_items_inventory = session.query(CurrentInventorySnapshot.item_id, func.sum(CurrentInventorySnapshot.availibility), func.sum(CurrentInventorySnapshot.reserved)).filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).group_by(CurrentInventorySnapshot.item_id).having(func.sum(CurrentInventorySnapshot.reserved) > 0).all()
4024 chandransh 1245
    return pending_items_inventory
4295 varun.gupt 1246
 
1247
def get_product_notifications(start_datetime):
1248
    '''
1249
    Returns a list of Product Notification objects each representing user requests for notification
1250
    '''
1251
    query = ProductNotification.query
3924 rajveer 1252
 
4295 varun.gupt 1253
    if start_datetime:
1254
        query = query.filter(ProductNotification.addedOn > start_datetime)
1255
 
1256
    notifications = query.order_by(desc('addedOn')).all()
1257
    return notifications
1258
 
1259
def get_product_notification_request_count(start_datetime):
1260
    '''
1261
    Returns list of items and the counts of product notification requests
1262
    '''
1263
    print start_datetime
1264
    query = session.query(ProductNotification, func.count(ProductNotification.email).label('count'))
1265
 
1266
    if start_datetime:
1267
        query = query.filter(ProductNotification.addedOn > start_datetime)
1268
 
1269
    counts = query.group_by(ProductNotification.item_id).order_by(desc('count')).all()
1270
    return counts
1271
 
766 rajveer 1272
def close_session():
1273
    if session.is_active:
1274
        print "session is active. closing it."
1399 rajveer 1275
        session.close()
3376 rajveer 1276
 
1277
def is_alive():
1278
    try:
1279
        session.query(Item.id).limit(1).one()
1280
        return True
1281
    except:
1282
        return False