Subversion Repositories SmartDukaan

Rev

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