Subversion Repositories SmartDukaan

Rev

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