Subversion Repositories SmartDukaan

Rev

Rev 4283 | Rev 4307 | 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")
826
 
4283 anupam.sin 827
    vendor = Vendor.get_by(id=vendorId)    
1341 chandransh 828
    try:
829
        item_pricing = VendorItemPricing.query.filter_by(vendor=vendor, item=item).one()
1347 chandransh 830
        return item_pricing
3244 chandransh 831
    except MultipleResultsFound:
1341 chandransh 832
        raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
3244 chandransh 833
    except NoResultFound:
1341 chandransh 834
        raise InventoryServiceException(111, "Missing pricing information for Vendor: " + vendor.name + " and Item: " + str(item_id))
835
 
1970 rajveer 836
def add_category(t_category):
837
    category = Category.get_by(id=t_category.id)
838
    if category is None:
839
        category = Category()
840
    category.id = t_category.id 
841
    category.label = t_category.label
842
    category.description = t_category.description
843
    category.parent_category_id = t_category.parent_category_id 
844
    session.commit()
845
    return True
846
 
847
def get_category(id):
848
    return Category.query.filter_by(id=id).first()
849
 
850
def get_all_categories():
851
    return Category.query.all()
852
 
1991 ankur.sing 853
 
854
def get_all_item_pricing(item_id):
855
    item = Item.query.filter_by(id=item_id).first()
856
    if item is None:
857
        raise InventoryServiceException(101, "Bad Item")
858
    item_pricing = VendorItemPricing.query.filter_by(item=item).all()
859
    return item_pricing
860
 
2116 ankur.sing 861
def get_item_mappings(item_id):
862
    item = Item.query.filter_by(id=item_id).first()
863
    if item is None:
864
        raise InventoryServiceException(101, "Bad Item")
865
    item_mappings = VendorItemMapping.query.filter_by(item=item).all()
866
    return item_mappings
867
 
868
def add_vendor_pricing(vendorItemPricing):
1991 ankur.sing 869
    if not vendorItemPricing:
870
        raise InventoryServiceException(108, "Bad vendorItemPricing in request")
871
    vendorId = vendorItemPricing.vendorId
872
    itemId = vendorItemPricing.itemId
873
 
874
    try:
875
        vendor = Vendor.query.filter_by(id=vendorId).one()
876
    except:
877
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
878
 
879
    try:
880
        item = Item.query.filter_by(id=itemId).one()
881
    except:
882
        raise InventoryServiceException(101, "Item not found for vendorId " + str(itemId))
883
 
2120 ankur.sing 884
    validate_vendor_prices(to_t_item(item), vendorItemPricing)
2065 ankur.sing 885
 
1991 ankur.sing 886
    try:
887
        ds_vendorItemPricing = VendorItemPricing.query.filter(and_(VendorItemPricing.vendor==vendor, VendorItemPricing.item==item)).one()
888
    except:
2116 ankur.sing 889
        ds_vendorItemPricing = VendorItemPricing()
890
        ds_vendorItemPricing.vendor = vendor
891
        ds_vendorItemPricing.item = item
1991 ankur.sing 892
 
893
    if vendorItemPricing.mop:
894
        ds_vendorItemPricing.mop = vendorItemPricing.mop
895
    if vendorItemPricing.dealerPrice:
896
        ds_vendorItemPricing.dealerPrice = vendorItemPricing.dealerPrice
897
    if vendorItemPricing.transferPrice:
2065 ankur.sing 898
        ds_vendorItemPricing.transfer_price = vendorItemPricing.transferPrice
1991 ankur.sing 899
 
900
    session.commit()
901
    return
902
 
2358 ankur.sing 903
def add_vendor_item_mapping(key, vendorItemMapping):
2116 ankur.sing 904
    if not vendorItemMapping:
905
        raise InventoryServiceException(108, "Bad vendorItemMapping in request")
906
    vendorId = vendorItemMapping.vendorId
907
    itemId = vendorItemMapping.itemId
908
 
909
    try:
910
        vendor = Vendor.query.filter_by(id=vendorId).one()
911
    except:
912
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
913
 
914
    try:
915
        item = Item.query.filter_by(id=itemId).one()
916
    except:
917
        raise InventoryServiceException(101, "Item not found for vendorId " + str(itemId))
918
 
919
    try:
2358 ankur.sing 920
        ds_vendorItemMapping = VendorItemMapping.query.filter(and_(VendorItemMapping.vendor==vendor, VendorItemMapping.item==item, VendorItemMapping.item_key==key)).one()
2116 ankur.sing 921
    except:
922
        ds_vendorItemMapping = VendorItemMapping()
923
        ds_vendorItemMapping.vendor = vendor
924
        ds_vendorItemMapping.item = item
2497 ankur.sing 925
    ds_vendorItemMapping.vendor_category = vendorItemMapping.vendorCategory
2116 ankur.sing 926
    ds_vendorItemMapping.item_key = vendorItemMapping.itemKey
927
 
928
    session.commit()
929
    return
930
 
2120 ankur.sing 931
def validate_item_prices(item):
2129 ankur.sing 932
    if item.mrp == None or item.sellingPrice == None or item.mrp == "" or item.sellingPrice == "":
933
        return
934
    if item.mrp < item.sellingPrice:
2120 ankur.sing 935
        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))
936
        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 937
    return
2120 ankur.sing 938
 
939
def validate_vendor_prices(item, vendorPrices):
2129 ankur.sing 940
    if item.mrp != None and item.mrp != "" and vendorPrices.mop != "" and item.mrp <  vendorPrices.mop:
2120 ankur.sing 941
        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))
942
        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)))
943
    if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
944
        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))
945
        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)))
946
    return
2065 ankur.sing 947
 
948
def get_all_vendors():
949
    return Vendor.query.all()
950
 
2116 ankur.sing 951
def check_similar_item(product_group, brand, model_number, color):
2129 ankur.sing 952
    query = Item.query
2428 ankur.sing 953
    query = query.filter_by(product_group=product_group)
954
    query = query.filter_by(brand=brand)
955
    query = query.filter_by(model_number=model_number)
2129 ankur.sing 956
    if color:
957
        query = query.filter_by(color=color)
958
    item = query.first()
2116 ankur.sing 959
    if item is None:
960
        return 0
961
    else:
962
        return item.id
2286 ankur.sing 963
 
964
def change_risky_flag(item_id, risky):
965
    item = get_item(item_id)
966
    if not item:
967
        raise InventoryServiceException(101, "Item missing in our database")
968
    try:
969
        log_risky_flag(item_id, risky)
970
    except:
971
        print "Not able to log risky flag change"
972
    item.risky = risky
4295 varun.gupt 973
    if not risky and item.status == status.PAUSED_BY_RISK:
2368 ankur.sing 974
        change_item_status(item.id, status.ACTIVE)
2286 ankur.sing 975
    session.commit()
976
 
2358 ankur.sing 977
def get_items_by_vendor_category(vendor_category):
978
    if not vendor_category:
979
        raise InventoryServiceException(101, "Invalid vendor category in request")
980
    query = Item.query.filter(and_(Item.hotspotCategory==vendor_category, Item.status != status.PHASED_OUT))
981
    items = query.all()
982
    return items
2116 ankur.sing 983
 
2358 ankur.sing 984
def get_risky_items():
985
    items = Item.query.filter_by(risky=True).all()
986
    return items
3008 rajveer 987
 
2809 rajveer 988
def get_similar_items_catalog_ids(start_index, stop_index, itemId):
3008 rajveer 989
    query = SimilarItems.query.filter_by(item_id=itemId).limit(stop_index-start_index)
990
    similar_items = query.all()
3289 rajveer 991
    return_list = []
992
    for similar_item in similar_items:
993
        isActive = False
994
        try:
995
            all_items = Item.query.filter_by(catalog_item_id=similar_item.catalog_item_id).all()
996
        except:
997
            continue
998
        for item in all_items:
999
            isActive = isActive or item.status == status.ACTIVE
1000
        if isActive:
1001
            return_list.append(similar_item.catalog_item_id)
1002
    return return_list
2809 rajveer 1003
 
3079 rajveer 1004
def add_product_notification(itemId, email):
1005
    try:
3470 rajveer 1006
        try:
1007
            product_notification = ProductNotification.query.filter_by(item_id=itemId, email=email).one()
1008
        except:
1009
            product_notification = ProductNotification()
1010
            product_notification.email = email
1011
            product_notification.item_id = itemId
3079 rajveer 1012
        product_notification.addedOn = datetime.datetime.now()
1013
        session.commit()
1014
        return True
1015
    except:
1016
        return False
3086 rajveer 1017
 
1018
 
1019
def send_product_notifications():
1020
    product_notifications = ProductNotification.query.all()
1021
    for product_notification in product_notifications:
1022
        item = product_notification.item
1023
        availability = __get_item_availability(item)
3309 rajveer 1024
        if availability > 0 and item.status == status.ACTIVE:
3086 rajveer 1025
            __enque_product_notification_email(product_notification.email, __get_product_name(item) , product_notification.addedOn, __get_product_url(item), item.id)
1026
            product_notification.delete()
1027
    session.commit()
1028
    return True
1029
 
1030
def __get_product_name(item):
1031
    product_name = item.brand + " " + item.model_name + " " + item.model_number
1032
    color = item.color
1033
    if color is not None and color != 'NA':
1034
        product_name = product_name + " (" + color + ")"
3201 rajveer 1035
    product_name = product_name.replace("  "," ")
3086 rajveer 1036
    return product_name
1037
 
1038
 
1039
def __get_product_url(item):
1040
    product_url = "http://www.saholic.com/mobile-phones/" + item.brand + "-" + item.model_name + "-" + item.model_number + "-" + str(item.catalog_item_id)
1041
    product_url = product_url.replace("--","-")
1042
    product_url = product_url.replace(" ","")
1043
    return product_url
1044
 
3348 varun.gupt 1045
def get_all_brands_by_category(category_id):
1046
    catm = CategoryManager()
1047
    child_categories = catm.getCategory(category_id).children_category_ids
1048
    brands = session.query(distinct(Item.brand)).filter(Item.category.in_(child_categories)).all()
1049
 
1050
    return [brand[0] for brand in brands]
3086 rajveer 1051
 
1052
def __enque_product_notification_email(email, product, date, url, itemId):
1053
 
1054
    html = """
1055
        <html>
1056
        <body>
1057
        <div>
1058
        <p>
1059
            Hi,<br /><br />
1060
            The product requested by you on $date is now available on saholic.com.
1061
        </p>
1062
 
1063
        <p>    
1064
        <strong>Product: $product </strong>
1065
        </p>
1066
 
1067
        <p>
1068
        Click the link below to visit the product: 
1069
        <br/>
1070
        $url
1071
        </p>
1072
        <p>
1073
        Regards,<br/>
1074
        Saholic Customer Support Team<br/>
1075
        www.saholic.com<br/>
1076
        Email: help@saholic.com<br/>
1077
        </p>
1078
        </div>
1079
        </body>
1080
        </html>
1081
        """
1082
 
1083
    html = Template(html).substitute(dict(product=product,date=date,url=url))
3079 rajveer 1084
 
3086 rajveer 1085
    try:
1086
        helper_client = HelperClient().get_client()
1087
        helper_client.saveUserEmailForSending(email, "", "Product requested by you is available now.", html, str(itemId), "ProductNotification")
1088
    except Exception as e:
1089
        print e
1090
 
3557 rajveer 1091
def get_all_sources():
1092
    sources = Source.query.all()
1093
    return [to_t_source(source) for source in sources]
3086 rajveer 1094
 
3557 rajveer 1095
def get_item_pricing_by_source(itemId, sourceId):
1096
    item = Item.query.filter_by(id=itemId).first()
1097
    if item is None:
1098
        raise InventoryServiceException(101, "Bad Item")
1099
 
1100
    source = Source.query.filter_by(id=sourceId).first()
1101
    if source is None:
1102
        raise InventoryServiceException(101, "Source not found for sourceId " + str(sourceId))
1103
 
1104
    item_pricing = SourceItemPricing.query.filter_by(source=source, item=item).first()
1105
    if item_pricing is None:
1106
        raise InventoryServiceException(101, "Pricing information not found for sourceId " + str(sourceId))
1107
    return item_pricing
1108
 
1109
def add_source_item_pricing(sourceItemPricing):
1110
    if not sourceItemPricing:
1111
        raise InventoryServiceException(108, "Bad sourceItemPricing in request")
1112
 
1113
    if not sourceItemPricing.sellingPrice:
1114
        raise InventoryServiceException(101, "Selling Price is not defined for sourceId " + str(sourceId))
1115
 
1116
    sourceId = sourceItemPricing.sourceId
1117
    itemId = sourceItemPricing.itemId
1118
 
1119
    item = Item.query.filter_by(id=itemId).first()
1120
    if item is None:
1121
        raise InventoryServiceException(101, "Bad Item")
1122
 
1123
    source = Source.query.filter_by(id=sourceId).first()
1124
    if source is None:
1125
        raise InventoryServiceException(101, "Source not found for sourceId " + str(sourceId))
1126
 
3564 rajveer 1127
    ds_sourceItemPricing = SourceItemPricing.get_by(source=source, item=item)
3557 rajveer 1128
    if ds_sourceItemPricing is None:
1129
        ds_sourceItemPricing = SourceItemPricing()
1130
        ds_sourceItemPricing.source = source
1131
        ds_sourceItemPricing.item = item
1132
 
1133
    if sourceItemPricing.mrp:
1134
        ds_sourceItemPricing.mrp = sourceItemPricing.mrp
1135
    ds_sourceItemPricing.sellingPrice = sourceItemPricing.sellingPrice
1136
 
1137
    session.commit()
1138
    return
1139
 
1140
def get_all_source_pricing(itemId):
1141
    item = Item.query.filter_by(id=itemId).first()
1142
    if item is None:
1143
        raise InventoryServiceException(101, "Bad Item")
1144
    source_pricing = SourceItemPricing.query.filter_by(item=item).all()
1145
    return source_pricing
1146
 
1147
 
1148
def get_item_for_source(item_id, sourceId):
1149
    item = get_item(item_id)
1150
    if sourceId == -1:
1151
        return item
1152
    try:
1153
        sip = get_item_pricing_by_source(item_id, sourceId)
1154
        item.sellingPrice = sip.sellingPrice
1155
        if sip.mrp:
1156
            item.mrp = sip.mrp
1157
    except:
1158
        print "No source pricing"
1159
    return item
1160
 
3872 chandransh 1161
def search_items(search_terms, offset, limit):
1162
    query = Item.query
1163
 
1164
    query_clause = []
1165
 
1166
    search_terms = ['%' + search_term + '%' for search_term in search_terms]
1167
 
1168
    for search_term in search_terms:
1169
        query_clause.append(Item.brand.like(search_term))
1170
        query_clause.append(Item.model_number.like(search_term))
1171
        query_clause.append(Item.model_name.like(search_term))
1172
 
1173
    query = query.filter(or_(*query_clause))
1174
 
1175
    query = query.order_by(Item.product_group, Item.brand, Item.model_number, Item.model_name).offset(offset)
1176
    if limit:
1177
        query = query.limit(limit)
1178
    items = query.all()
1179
    return items
1180
 
1181
def get_search_result_count(search_terms):
1182
    query = Item.query
1183
 
1184
    query_clause = []
1185
 
1186
    search_terms = ['%' + search_term + '%' for search_term in search_terms]
1187
 
1188
    for search_term in search_terms:
1189
        query_clause.append(Item.brand.like(search_term))
1190
        query_clause.append(Item.model_number.like(search_term))
1191
        query_clause.append(Item.model_name.like(search_term))
1192
 
1193
    query = query.filter(or_(*query_clause))
1194
 
1195
    return query.count()
1196
 
3924 rajveer 1197
def __clear_homepage_cache():
1198
    try:
1199
        # create a password manager
1200
        password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
1201
        # Add the username and password.
1202
        configclient = ConfigClient()
1203
        ips = configclient.get_property("production_servers_public_ips");
1204
        ips = ips.split(" ")
1205
 
1206
        for ip in ips:
1207
            top_level_url = "http://" + ip + ":8080/"
1208
            password_mgr.add_password(None, top_level_url, "saholic", "shop2020")
1209
            handler = urllib2.HTTPBasicAuthHandler(password_mgr)
1210
 
1211
            opener = urllib2.build_opener(handler)
1212
 
1213
            # use the opener to fetch a URL
1214
            res = opener.open(top_level_url + "cache-admin/HomePageSnippets?_method=delete")
1215
            print "Successfully cleared home page cache" + res.read()
1216
    except:
1217
        print "Unable to clear cache, still should continue with other operations"
4024 chandransh 1218
 
4062 chandransh 1219
def get_pending_orders_inventory(vendor_id=1):
4024 chandransh 1220
    """
1221
    Returns a list of inventory stock for items for which there are pending orders.
1222
    """
4062 chandransh 1223
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter_by(vendor_id=vendor_id).all()]
4064 chandransh 1224
    pending_items_inventory = []
1225
    if warehouse_ids:
1226
        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 1227
    return pending_items_inventory
4295 varun.gupt 1228
 
1229
def get_product_notifications(start_datetime):
1230
    '''
1231
    Returns a list of Product Notification objects each representing user requests for notification
1232
    '''
1233
    query = ProductNotification.query
3924 rajveer 1234
 
4295 varun.gupt 1235
    if start_datetime:
1236
        query = query.filter(ProductNotification.addedOn > start_datetime)
1237
 
1238
    notifications = query.order_by(desc('addedOn')).all()
1239
    return notifications
1240
 
1241
def get_product_notification_request_count(start_datetime):
1242
    '''
1243
    Returns list of items and the counts of product notification requests
1244
    '''
1245
    print start_datetime
1246
    query = session.query(ProductNotification, func.count(ProductNotification.email).label('count'))
1247
 
1248
    if start_datetime:
1249
        query = query.filter(ProductNotification.addedOn > start_datetime)
1250
 
1251
    counts = query.group_by(ProductNotification.item_id).order_by(desc('count')).all()
1252
    return counts
1253
 
766 rajveer 1254
def close_session():
1255
    if session.is_active:
1256
        print "session is active. closing it."
1399 rajveer 1257
        session.close()
3376 rajveer 1258
 
1259
def is_alive():
1260
    try:
1261
        session.query(Item.id).limit(1).one()
1262
        return True
1263
    except:
1264
        return False