Subversion Repositories SmartDukaan

Rev

Rev 4315 | Rev 4318 | 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
4317 varun.gupt 602
        except Exception as e:
603
            print e
785 rajveer 604
            availability = 0    
3503 chandransh 605
        if availability > max_availability:
643 chandransh 606
            warehouse_retid = warehouse_id
3503 chandransh 607
            max_availability = availability
608
        total_availability = total_availability + availability
2341 chandransh 609
 
3355 chandransh 610
    #If no warehouse could be found, use the preferred warehouse for this item
643 chandransh 611
    if warehouse_retid == -1:
759 chandransh 612
        # This is the case when all warehouses have exhausted their
613
        # inventory of this item or no warehouse is available in this
614
        # location.
1416 chandransh 615
        warehouse_retid = int(item.preferredWarehouse)
2344 chandransh 616
        warehouse = Warehouse.get_by(id=warehouse_retid)
2341 chandransh 617
        try:
618
            current_inventory_snapshot = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_retid, item_id = item_id).one()
3503 chandransh 619
            max_availability = current_inventory_snapshot.availibility - current_inventory_snapshot.reserved
4317 varun.gupt 620
        except Exception as e:
621
            print e
3503 chandransh 622
            max_availability = 0
623
        total_availability = max_availability
643 chandransh 624
 
4317 varun.gupt 625
    if item.expectedDelay is None:
626
        print 'expectedDelay field for this item was Null. Resetting it to 0'
627
        item.expectedDelay = 0
628
 
3503 chandransh 629
    return [warehouse.logisticsLocation, warehouse_retid, total_availability, item.expectedDelay]
2341 chandransh 630
 
122 ashish 631
def get_warehouses_for_item(item_id):
643 chandransh 632
 
122 ashish 633
    if not item_id:
634
        raise InventoryServiceException(101, "bad item_id")
635 rajveer 635
    item = get_item(item_id)
122 ashish 636
 
637
    if not item:
638
        raise InventoryServiceException(101, "bad item")
639
 
483 rajveer 640
    warehouses = item.currentInventory.warehouse
501 rajveer 641
    return warehouses
642
 
2404 chandransh 643
def get_child_categories(category):
644
    cm = CategoryManager()
2621 varun.gupt 645
    cat = cm.getCategory(category)
646
    return cat.children_category_ids if cat else None
2404 chandransh 647
 
626 chandransh 648
def get_best_sellers(start_index, stop_index, category=-1):
2404 chandransh 649
    '''
650
    Returns the Best Sellers between the start and the stop index in the given category
651
    '''
1926 rajveer 652
    query = get_best_sellers_query(category, None)
1098 chandransh 653
    best_sellers = query.all()[start_index:stop_index]
621 chandransh 654
    return get_thrift_item_list(best_sellers)
655
 
2093 chandransh 656
def get_best_sellers_count(category=-1):
2404 chandransh 657
    '''
658
    Returns the number of best sellers in the given category
659
    '''
1926 rajveer 660
    count = get_best_sellers_query(category, None).count()
1120 rajveer 661
    if count is None:
662
        count = 0
766 rajveer 663
    return count
621 chandransh 664
 
1926 rajveer 665
def get_best_sellers_catalog_ids(start_index, stop_index, brand, category=-1):
2404 chandransh 666
    '''
667
    Returns the Best sellers for the given brand and category between the start and the stop index.
668
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
669
    '''
1926 rajveer 670
    query = get_best_sellers_query(category, brand)
1098 chandransh 671
    best_sellers = query.all()[start_index:stop_index]
621 chandransh 672
    return [item.catalog_item_id for item in best_sellers]
1970 rajveer 673
 
1926 rajveer 674
def get_best_sellers_query(category, brand):
2404 chandransh 675
    '''
676
    Returns the query to be used for getting Best Sellers.
677
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
678
    '''
1098 chandransh 679
    query = Item.query.filter_by(status=status.ACTIVE).filter(Item.bestSellingRank != None)
626 chandransh 680
    if category != -1:
1970 rajveer 681
        all_categories = [category]
682
        child_categories = get_child_categories(category)
683
        if child_categories is not None:
684
            all_categories = all_categories + child_categories 
685
        query = query.filter(Item.category.in_(all_categories))
1926 rajveer 686
    if brand is not None:
687
        query = query.filter_by(brand=brand)
1098 chandransh 688
    query = query.order_by(asc(Item.bestSellingRank))
621 chandransh 689
    return query
609 chandransh 690
 
1098 chandransh 691
def get_best_deals(category=-1):
2404 chandransh 692
    '''
693
    Returns the Best deals in the given category. Ignores the category if it's passed as -1.
694
    '''
695
    query = get_best_deals_query(Item, category, None)
1098 chandransh 696
    items = query.all()
609 chandransh 697
    return get_thrift_item_list(items)
698
 
1098 chandransh 699
def get_best_deals_count(category=-1):
2404 chandransh 700
    '''
701
    Returns the count of best deals in the given category.
702
    Ignores the category if it's -1.
703
    '''
704
    count = get_best_deals_counting_query(func.count(distinct(Item.catalog_item_id)), category, None).scalar()
1120 rajveer 705
    if count is None:
706
        count = 0
766 rajveer 707
    return count
501 rajveer 708
 
1926 rajveer 709
def get_best_deals_catalog_ids(start_index, stop_index, brand, category=-1):
2404 chandransh 710
    '''
711
    Returns the catalog_item_ids of best deal items for the given brand and category.
712
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
713
    '''
714
    query = get_best_deals_query(Item, category, brand)
1098 chandransh 715
    best_deal_items = query.all()[start_index:stop_index]
716
    return [item.catalog_item_id for item in best_deal_items]
717
 
2404 chandransh 718
def get_best_deals_counting_query(obj, category, brand):
719
    '''
720
    Returns the query to be used to select the best deals in the given brand and category.
721
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
722
    '''
723
    query = session.query(obj).filter_by(status=status.ACTIVE).filter(Item.bestDealValue != None)
626 chandransh 724
    if category != -1:
1970 rajveer 725
        all_categories = [category]
726
        child_categories = get_child_categories(category)
727
        if child_categories is not None:
728
            all_categories = all_categories + child_categories 
729
        query = query.filter(Item.category.in_(all_categories))
1926 rajveer 730
    if brand is not None:
731
        query = query.filter_by(brand=brand)
2404 chandransh 732
    return query
733
 
734
def get_best_deals_query(obj, category, brand):
735
    '''
736
    Returns the query to be used to get the best deals in the given category and brand.
737
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
738
    '''
739
    query = get_best_deals_counting_query(obj, category, brand)
1098 chandransh 740
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.bestDealValue))
741
    return query
609 chandransh 742
 
1098 chandransh 743
def get_latest_arrivals(limit, category=-1):
2404 chandransh 744
    '''
745
    Returns up to limit number of Latest Arrivals in the given category.
746
    '''
2975 chandransh 747
    categories = []
748
    if category != -1:
749
        categories = [category]
750
    query = get_latest_arrivals_query(Item, categories, None)
1098 chandransh 751
    items = query.all()[0:limit]
609 chandransh 752
    return get_thrift_item_list(items)
598 chandransh 753
 
1098 chandransh 754
def get_latest_arrivals_count(limit, category=-1):
2404 chandransh 755
    '''
756
    Returns the number of latest arrivals which will be displayed on the website.
3016 chandransh 757
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 758
    '''
2975 chandransh 759
    categories = []
760
    if category != -1:
761
        categories = [category]
762
    count = get_latest_arrivals_counting_query(func.count(distinct(Item.catalog_item_id)), categories, None).scalar()
1120 rajveer 763
    if count is None:
764
        count = 0
765
    count = min(count, limit)
766 rajveer 766
    return count
602 chandransh 767
 
2975 chandransh 768
def get_latest_arrivals_catalog_ids(start_index, stop_index, brand, categories=[]):
2404 chandransh 769
    '''
770
    Returns the catalog_item_ids of the latest arrivals between the start and the stop index
3016 chandransh 771
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 772
    '''
2975 chandransh 773
    query = get_latest_arrivals_query(Item, categories, brand)
1098 chandransh 774
    latest_arrivals = query.all()[start_index:stop_index]
775
    return [item.catalog_item_id for item in latest_arrivals]
776
 
2975 chandransh 777
def get_latest_arrivals_counting_query(obj, categories, brand):
2404 chandransh 778
    '''
779
    Returns the query to be used to count Latest arrivals.
3016 chandransh 780
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 781
    '''
782
    query = session.query(obj).filter_by(status=status.ACTIVE)
2975 chandransh 783
 
784
    all_categories = []
785
    for category in categories:
786
        all_categories.append(category)
1970 rajveer 787
        child_categories = get_child_categories(category)
2975 chandransh 788
        if child_categories:
789
            all_categories = all_categories + child_categories
790
    if all_categories: 
1970 rajveer 791
        query = query.filter(Item.category.in_(all_categories))
2975 chandransh 792
 
1926 rajveer 793
    if brand is not None:
794
        query = query.filter_by(brand=brand)
2404 chandransh 795
    return query
796
 
2975 chandransh 797
def get_latest_arrivals_query(obj, categories, brand):
2404 chandransh 798
    '''
799
    Returns the query to be used to retrieve Latest Arrivals.
800
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
801
    '''
2975 chandransh 802
    query = get_latest_arrivals_counting_query(obj, categories, brand)
1098 chandransh 803
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.startDate))
804
    return query
609 chandransh 805
 
806
def get_thrift_item_list(items):
1098 chandransh 807
    return [to_t_item(item) for item in items if item != None]
635 rajveer 808
 
1155 rajveer 809
def generate_new_entity_id():
810
    generator =  EntityIDGenerator.query.one()
811
    id = generator.id + 1
812
    generator.id = id
813
    session.commit()
814
    return id
815
 
635 rajveer 816
def put_category_object(object):
817
    category = Category.get_by(id=1)
818
    if category is None:
819
        category = Category()
820
    category.object = object    
821
    session.commit()
822
    return True
823
 
824
def get_category_object():
766 rajveer 825
    object = Category.get_by(id=1).object
826
    return object
827
 
4283 anupam.sin 828
def get_item_pricing(item_id, vendorId):
1341 chandransh 829
    item = Item.query.filter_by(id=item_id).first()
830
    if item is None:
831
        raise InventoryServiceException(101, "Bad Item")
4307 anupam.sin 832
    '''
833
    if vendor id is -1 then we calculate an average transfer price to be populated
834
    at the time of order creation. This will be later updated with actual transfer price
835
    at the time of billing.
836
    '''
837
    if(vendorId == -1):
838
        try:
839
            item_pricings = VendorItemPricing.query.filter_by(item=item).all()
4315 anupam.sin 840
            if item_pricings:
4307 anupam.sin 841
                for item_pricing in item_pricings:
4315 anupam.sin 842
                    total =+ item_pricing.transfer_price
843
                avg = total / len(item_pricings)
844
                item_pricing.transfer_price = avg
845
                return item_pricing
4307 anupam.sin 846
        except:
847
            raise InventoryServiceException(101, "Item pricing not found ")
4283 anupam.sin 848
    vendor = Vendor.get_by(id=vendorId)    
1341 chandransh 849
    try:
850
        item_pricing = VendorItemPricing.query.filter_by(vendor=vendor, item=item).one()
1347 chandransh 851
        return item_pricing
3244 chandransh 852
    except MultipleResultsFound:
1341 chandransh 853
        raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
3244 chandransh 854
    except NoResultFound:
1341 chandransh 855
        raise InventoryServiceException(111, "Missing pricing information for Vendor: " + vendor.name + " and Item: " + str(item_id))
856
 
1970 rajveer 857
def add_category(t_category):
858
    category = Category.get_by(id=t_category.id)
859
    if category is None:
860
        category = Category()
861
    category.id = t_category.id 
862
    category.label = t_category.label
863
    category.description = t_category.description
864
    category.parent_category_id = t_category.parent_category_id 
865
    session.commit()
866
    return True
867
 
868
def get_category(id):
869
    return Category.query.filter_by(id=id).first()
870
 
871
def get_all_categories():
872
    return Category.query.all()
873
 
1991 ankur.sing 874
 
875
def get_all_item_pricing(item_id):
876
    item = Item.query.filter_by(id=item_id).first()
877
    if item is None:
878
        raise InventoryServiceException(101, "Bad Item")
879
    item_pricing = VendorItemPricing.query.filter_by(item=item).all()
880
    return item_pricing
881
 
2116 ankur.sing 882
def get_item_mappings(item_id):
883
    item = Item.query.filter_by(id=item_id).first()
884
    if item is None:
885
        raise InventoryServiceException(101, "Bad Item")
886
    item_mappings = VendorItemMapping.query.filter_by(item=item).all()
887
    return item_mappings
888
 
889
def add_vendor_pricing(vendorItemPricing):
1991 ankur.sing 890
    if not vendorItemPricing:
891
        raise InventoryServiceException(108, "Bad vendorItemPricing in request")
892
    vendorId = vendorItemPricing.vendorId
893
    itemId = vendorItemPricing.itemId
894
 
895
    try:
896
        vendor = Vendor.query.filter_by(id=vendorId).one()
897
    except:
898
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
899
 
900
    try:
901
        item = Item.query.filter_by(id=itemId).one()
902
    except:
903
        raise InventoryServiceException(101, "Item not found for vendorId " + str(itemId))
904
 
2120 ankur.sing 905
    validate_vendor_prices(to_t_item(item), vendorItemPricing)
2065 ankur.sing 906
 
1991 ankur.sing 907
    try:
908
        ds_vendorItemPricing = VendorItemPricing.query.filter(and_(VendorItemPricing.vendor==vendor, VendorItemPricing.item==item)).one()
909
    except:
2116 ankur.sing 910
        ds_vendorItemPricing = VendorItemPricing()
911
        ds_vendorItemPricing.vendor = vendor
912
        ds_vendorItemPricing.item = item
1991 ankur.sing 913
 
914
    if vendorItemPricing.mop:
915
        ds_vendorItemPricing.mop = vendorItemPricing.mop
916
    if vendorItemPricing.dealerPrice:
917
        ds_vendorItemPricing.dealerPrice = vendorItemPricing.dealerPrice
918
    if vendorItemPricing.transferPrice:
2065 ankur.sing 919
        ds_vendorItemPricing.transfer_price = vendorItemPricing.transferPrice
1991 ankur.sing 920
 
921
    session.commit()
922
    return
923
 
2358 ankur.sing 924
def add_vendor_item_mapping(key, vendorItemMapping):
2116 ankur.sing 925
    if not vendorItemMapping:
926
        raise InventoryServiceException(108, "Bad vendorItemMapping in request")
927
    vendorId = vendorItemMapping.vendorId
928
    itemId = vendorItemMapping.itemId
929
 
930
    try:
931
        vendor = Vendor.query.filter_by(id=vendorId).one()
932
    except:
933
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
934
 
935
    try:
936
        item = Item.query.filter_by(id=itemId).one()
937
    except:
938
        raise InventoryServiceException(101, "Item not found for vendorId " + str(itemId))
939
 
940
    try:
2358 ankur.sing 941
        ds_vendorItemMapping = VendorItemMapping.query.filter(and_(VendorItemMapping.vendor==vendor, VendorItemMapping.item==item, VendorItemMapping.item_key==key)).one()
2116 ankur.sing 942
    except:
943
        ds_vendorItemMapping = VendorItemMapping()
944
        ds_vendorItemMapping.vendor = vendor
945
        ds_vendorItemMapping.item = item
2497 ankur.sing 946
    ds_vendorItemMapping.vendor_category = vendorItemMapping.vendorCategory
2116 ankur.sing 947
    ds_vendorItemMapping.item_key = vendorItemMapping.itemKey
948
 
949
    session.commit()
950
    return
951
 
2120 ankur.sing 952
def validate_item_prices(item):
2129 ankur.sing 953
    if item.mrp == None or item.sellingPrice == None or item.mrp == "" or item.sellingPrice == "":
954
        return
955
    if item.mrp < item.sellingPrice:
2120 ankur.sing 956
        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))
957
        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 958
    return
2120 ankur.sing 959
 
960
def validate_vendor_prices(item, vendorPrices):
2129 ankur.sing 961
    if item.mrp != None and item.mrp != "" and vendorPrices.mop != "" and item.mrp <  vendorPrices.mop:
2120 ankur.sing 962
        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))
963
        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)))
964
    if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
965
        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))
966
        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)))
967
    return
2065 ankur.sing 968
 
969
def get_all_vendors():
970
    return Vendor.query.all()
971
 
2116 ankur.sing 972
def check_similar_item(product_group, brand, model_number, color):
2129 ankur.sing 973
    query = Item.query
2428 ankur.sing 974
    query = query.filter_by(product_group=product_group)
975
    query = query.filter_by(brand=brand)
976
    query = query.filter_by(model_number=model_number)
2129 ankur.sing 977
    if color:
978
        query = query.filter_by(color=color)
979
    item = query.first()
2116 ankur.sing 980
    if item is None:
981
        return 0
982
    else:
983
        return item.id
2286 ankur.sing 984
 
985
def change_risky_flag(item_id, risky):
986
    item = get_item(item_id)
987
    if not item:
988
        raise InventoryServiceException(101, "Item missing in our database")
989
    try:
990
        log_risky_flag(item_id, risky)
991
    except:
992
        print "Not able to log risky flag change"
993
    item.risky = risky
4295 varun.gupt 994
    if not risky and item.status == status.PAUSED_BY_RISK:
2368 ankur.sing 995
        change_item_status(item.id, status.ACTIVE)
2286 ankur.sing 996
    session.commit()
997
 
2358 ankur.sing 998
def get_items_by_vendor_category(vendor_category):
999
    if not vendor_category:
1000
        raise InventoryServiceException(101, "Invalid vendor category in request")
1001
    query = Item.query.filter(and_(Item.hotspotCategory==vendor_category, Item.status != status.PHASED_OUT))
1002
    items = query.all()
1003
    return items
2116 ankur.sing 1004
 
2358 ankur.sing 1005
def get_risky_items():
1006
    items = Item.query.filter_by(risky=True).all()
1007
    return items
3008 rajveer 1008
 
2809 rajveer 1009
def get_similar_items_catalog_ids(start_index, stop_index, itemId):
3008 rajveer 1010
    query = SimilarItems.query.filter_by(item_id=itemId).limit(stop_index-start_index)
1011
    similar_items = query.all()
3289 rajveer 1012
    return_list = []
1013
    for similar_item in similar_items:
1014
        isActive = False
1015
        try:
1016
            all_items = Item.query.filter_by(catalog_item_id=similar_item.catalog_item_id).all()
1017
        except:
1018
            continue
1019
        for item in all_items:
1020
            isActive = isActive or item.status == status.ACTIVE
1021
        if isActive:
1022
            return_list.append(similar_item.catalog_item_id)
1023
    return return_list
2809 rajveer 1024
 
3079 rajveer 1025
def add_product_notification(itemId, email):
1026
    try:
3470 rajveer 1027
        try:
1028
            product_notification = ProductNotification.query.filter_by(item_id=itemId, email=email).one()
1029
        except:
1030
            product_notification = ProductNotification()
1031
            product_notification.email = email
1032
            product_notification.item_id = itemId
3079 rajveer 1033
        product_notification.addedOn = datetime.datetime.now()
1034
        session.commit()
1035
        return True
1036
    except:
1037
        return False
3086 rajveer 1038
 
1039
 
1040
def send_product_notifications():
1041
    product_notifications = ProductNotification.query.all()
1042
    for product_notification in product_notifications:
1043
        item = product_notification.item
1044
        availability = __get_item_availability(item)
3309 rajveer 1045
        if availability > 0 and item.status == status.ACTIVE:
3086 rajveer 1046
            __enque_product_notification_email(product_notification.email, __get_product_name(item) , product_notification.addedOn, __get_product_url(item), item.id)
1047
            product_notification.delete()
1048
    session.commit()
1049
    return True
1050
 
1051
def __get_product_name(item):
1052
    product_name = item.brand + " " + item.model_name + " " + item.model_number
1053
    color = item.color
1054
    if color is not None and color != 'NA':
1055
        product_name = product_name + " (" + color + ")"
3201 rajveer 1056
    product_name = product_name.replace("  "," ")
3086 rajveer 1057
    return product_name
1058
 
1059
 
1060
def __get_product_url(item):
1061
    product_url = "http://www.saholic.com/mobile-phones/" + item.brand + "-" + item.model_name + "-" + item.model_number + "-" + str(item.catalog_item_id)
1062
    product_url = product_url.replace("--","-")
1063
    product_url = product_url.replace(" ","")
1064
    return product_url
1065
 
3348 varun.gupt 1066
def get_all_brands_by_category(category_id):
1067
    catm = CategoryManager()
1068
    child_categories = catm.getCategory(category_id).children_category_ids
1069
    brands = session.query(distinct(Item.brand)).filter(Item.category.in_(child_categories)).all()
1070
 
1071
    return [brand[0] for brand in brands]
3086 rajveer 1072
 
1073
def __enque_product_notification_email(email, product, date, url, itemId):
1074
 
1075
    html = """
1076
        <html>
1077
        <body>
1078
        <div>
1079
        <p>
1080
            Hi,<br /><br />
1081
            The product requested by you on $date is now available on saholic.com.
1082
        </p>
1083
 
1084
        <p>    
1085
        <strong>Product: $product </strong>
1086
        </p>
1087
 
1088
        <p>
1089
        Click the link below to visit the product: 
1090
        <br/>
1091
        $url
1092
        </p>
1093
        <p>
1094
        Regards,<br/>
1095
        Saholic Customer Support Team<br/>
1096
        www.saholic.com<br/>
1097
        Email: help@saholic.com<br/>
1098
        </p>
1099
        </div>
1100
        </body>
1101
        </html>
1102
        """
1103
 
1104
    html = Template(html).substitute(dict(product=product,date=date,url=url))
3079 rajveer 1105
 
3086 rajveer 1106
    try:
1107
        helper_client = HelperClient().get_client()
1108
        helper_client.saveUserEmailForSending(email, "", "Product requested by you is available now.", html, str(itemId), "ProductNotification")
1109
    except Exception as e:
1110
        print e
1111
 
3557 rajveer 1112
def get_all_sources():
1113
    sources = Source.query.all()
1114
    return [to_t_source(source) for source in sources]
3086 rajveer 1115
 
3557 rajveer 1116
def get_item_pricing_by_source(itemId, sourceId):
1117
    item = Item.query.filter_by(id=itemId).first()
1118
    if item is None:
1119
        raise InventoryServiceException(101, "Bad Item")
1120
 
1121
    source = Source.query.filter_by(id=sourceId).first()
1122
    if source is None:
1123
        raise InventoryServiceException(101, "Source not found for sourceId " + str(sourceId))
1124
 
1125
    item_pricing = SourceItemPricing.query.filter_by(source=source, item=item).first()
1126
    if item_pricing is None:
1127
        raise InventoryServiceException(101, "Pricing information not found for sourceId " + str(sourceId))
1128
    return item_pricing
1129
 
1130
def add_source_item_pricing(sourceItemPricing):
1131
    if not sourceItemPricing:
1132
        raise InventoryServiceException(108, "Bad sourceItemPricing in request")
1133
 
1134
    if not sourceItemPricing.sellingPrice:
1135
        raise InventoryServiceException(101, "Selling Price is not defined for sourceId " + str(sourceId))
1136
 
1137
    sourceId = sourceItemPricing.sourceId
1138
    itemId = sourceItemPricing.itemId
1139
 
1140
    item = Item.query.filter_by(id=itemId).first()
1141
    if item is None:
1142
        raise InventoryServiceException(101, "Bad Item")
1143
 
1144
    source = Source.query.filter_by(id=sourceId).first()
1145
    if source is None:
1146
        raise InventoryServiceException(101, "Source not found for sourceId " + str(sourceId))
1147
 
3564 rajveer 1148
    ds_sourceItemPricing = SourceItemPricing.get_by(source=source, item=item)
3557 rajveer 1149
    if ds_sourceItemPricing is None:
1150
        ds_sourceItemPricing = SourceItemPricing()
1151
        ds_sourceItemPricing.source = source
1152
        ds_sourceItemPricing.item = item
1153
 
1154
    if sourceItemPricing.mrp:
1155
        ds_sourceItemPricing.mrp = sourceItemPricing.mrp
1156
    ds_sourceItemPricing.sellingPrice = sourceItemPricing.sellingPrice
1157
 
1158
    session.commit()
1159
    return
1160
 
1161
def get_all_source_pricing(itemId):
1162
    item = Item.query.filter_by(id=itemId).first()
1163
    if item is None:
1164
        raise InventoryServiceException(101, "Bad Item")
1165
    source_pricing = SourceItemPricing.query.filter_by(item=item).all()
1166
    return source_pricing
1167
 
1168
 
1169
def get_item_for_source(item_id, sourceId):
1170
    item = get_item(item_id)
1171
    if sourceId == -1:
1172
        return item
1173
    try:
1174
        sip = get_item_pricing_by_source(item_id, sourceId)
1175
        item.sellingPrice = sip.sellingPrice
1176
        if sip.mrp:
1177
            item.mrp = sip.mrp
1178
    except:
1179
        print "No source pricing"
1180
    return item
1181
 
3872 chandransh 1182
def search_items(search_terms, offset, limit):
1183
    query = Item.query
1184
 
1185
    query_clause = []
1186
 
1187
    search_terms = ['%' + search_term + '%' for search_term in search_terms]
1188
 
1189
    for search_term in search_terms:
1190
        query_clause.append(Item.brand.like(search_term))
1191
        query_clause.append(Item.model_number.like(search_term))
1192
        query_clause.append(Item.model_name.like(search_term))
1193
 
1194
    query = query.filter(or_(*query_clause))
1195
 
1196
    query = query.order_by(Item.product_group, Item.brand, Item.model_number, Item.model_name).offset(offset)
1197
    if limit:
1198
        query = query.limit(limit)
1199
    items = query.all()
1200
    return items
1201
 
1202
def get_search_result_count(search_terms):
1203
    query = Item.query
1204
 
1205
    query_clause = []
1206
 
1207
    search_terms = ['%' + search_term + '%' for search_term in search_terms]
1208
 
1209
    for search_term in search_terms:
1210
        query_clause.append(Item.brand.like(search_term))
1211
        query_clause.append(Item.model_number.like(search_term))
1212
        query_clause.append(Item.model_name.like(search_term))
1213
 
1214
    query = query.filter(or_(*query_clause))
1215
 
1216
    return query.count()
1217
 
3924 rajveer 1218
def __clear_homepage_cache():
1219
    try:
1220
        # create a password manager
1221
        password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
1222
        # Add the username and password.
1223
        configclient = ConfigClient()
4310 rajveer 1224
        ips = configclient.get_property("production_servers_private_ips");
3924 rajveer 1225
        ips = ips.split(" ")
1226
 
1227
        for ip in ips:
4310 rajveer 1228
            try:
1229
                top_level_url = "http://" + ip + ":8080/"
1230
                password_mgr.add_password(None, top_level_url, "saholic", "shop2020")
1231
                handler = urllib2.HTTPBasicAuthHandler(password_mgr)
3924 rajveer 1232
 
4310 rajveer 1233
                opener = urllib2.build_opener(handler)
3924 rajveer 1234
 
4310 rajveer 1235
                # use the opener to fetch a URL
1236
                res = opener.open(top_level_url + "cache-admin/HomePageSnippets?_method=delete")
1237
                print "Successfully cleared home page cache" + res.read()
1238
            except:
1239
                print "Unable to clear home page cache" + res.read()
3924 rajveer 1240
    except:
1241
        print "Unable to clear cache, still should continue with other operations"
4024 chandransh 1242
 
4062 chandransh 1243
def get_pending_orders_inventory(vendor_id=1):
4024 chandransh 1244
    """
1245
    Returns a list of inventory stock for items for which there are pending orders.
1246
    """
4062 chandransh 1247
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter_by(vendor_id=vendor_id).all()]
4064 chandransh 1248
    pending_items_inventory = []
1249
    if warehouse_ids:
1250
        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 1251
    return pending_items_inventory
4295 varun.gupt 1252
 
1253
def get_product_notifications(start_datetime):
1254
    '''
1255
    Returns a list of Product Notification objects each representing user requests for notification
1256
    '''
1257
    query = ProductNotification.query
3924 rajveer 1258
 
4295 varun.gupt 1259
    if start_datetime:
1260
        query = query.filter(ProductNotification.addedOn > start_datetime)
1261
 
1262
    notifications = query.order_by(desc('addedOn')).all()
1263
    return notifications
1264
 
1265
def get_product_notification_request_count(start_datetime):
1266
    '''
1267
    Returns list of items and the counts of product notification requests
1268
    '''
1269
    print start_datetime
1270
    query = session.query(ProductNotification, func.count(ProductNotification.email).label('count'))
1271
 
1272
    if start_datetime:
1273
        query = query.filter(ProductNotification.addedOn > start_datetime)
1274
 
1275
    counts = query.group_by(ProductNotification.item_id).order_by(desc('count')).all()
1276
    return counts
1277
 
766 rajveer 1278
def close_session():
1279
    if session.is_active:
1280
        print "session is active. closing it."
1399 rajveer 1281
        session.close()
3376 rajveer 1282
 
1283
def is_alive():
1284
    try:
1285
        session.query(Item.id).limit(1).one()
1286
        return True
1287
    except:
1288
        return False