Subversion Repositories SmartDukaan

Rev

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