Subversion Repositories SmartDukaan

Rev

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