Subversion Repositories SmartDukaan

Rev

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