Subversion Repositories SmartDukaan

Rev

Rev 4335 | Rev 4341 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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