Subversion Repositories SmartDukaan

Rev

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